March 05, 2012
On Monday, 5 March 2012 at 22:50:46 UTC, H. S. Teoh wrote:
> In theory, we *could* have druntime install a handler for SIGSEGV upon program startup that prints a stacktrace and
> exits

This sounds like a good idea to me.

> (or do whatever the
> equivalent is on Windows, if compiled on Windows).

On Windows, hardware exceptions are turned into D exceptions
by the SEH system.

The source is in druntime/src/rt/deh.d

You can catch null pointers on Windows if you want; the
OS makes this possible.
March 05, 2012
On 3/5/12 2:31 PM, Steven Schveighoffer wrote:
> On Mon, 05 Mar 2012 05:38:20 -0500, Walter Bright
> <newshound2@digitalmars.com> wrote:
>> I don't get this at all. I find it trivial to run the program with a
>> debugger:
>>
>> gdb foo
>> >run
>>
>> that's it.
>
> This argument continually irks me to no end. It seems like the trusty
> (rusty?) sword you always pull out when defending the current behavior,
> but it falls flat on its face when a programmer is faced with a Seg
> Fault that has occurred on a program that was running for several
> days/weeks, possibly not in his development environment, and now he must
> run it via a debugger to wait another several days/weeks to (hopefully)
> get the same error.
>
> Please stop using this argument, it's only valid on trivial bugs that
> crash immediately during development.

I second that.

Andrei


March 06, 2012
On Monday, 5 March 2012 at 04:39:59 UTC, Adam D. Ruppe wrote:

> Huh, I thought there was one in phobos by now.
>
> You could spin your own with something like this:
>
> struct NotNull(T) {
>   T t;
>   alias t this;
>   @disable this();
>   @disable this(typeof(null));
>   this(T value) {
>      assert(value !is null);
>      t = value;
>   }
>
>   @disable typeof(this) opAssign(typeof(null));
>   typeof(this) opAssign(T rhs) {
>       assert(rhs !is null);
>       t = rhs;
>       return this;
>   }
> }
>

The opAssign kills all type safety. I think only NotNull!T should be accepted... So "foo = bar" won't compile if bar is nullable. To fix, "foo = NotNull(bar)",

March 06, 2012
On Tuesday, 6 March 2012 at 00:01:20 UTC, Jason House wrote:
> The opAssign kills all type safety. I think only NotNull!T should be accepted... So "foo = bar" won't compile if bar is nullable. To fix, "foo = NotNull(bar)",

In both cases, the assert(x !is null), whether in
opAssign or in the constructor, is going to fire,
preventing the assignment.

Losing the opAssign would force you to think about
it, but I was concerned that it'd make it annoying
to use in a case where you already know it is not
null.

Perhaps worth it? I'm undecided. The constructor is
the important part, definitely.
March 06, 2012
Jason House:

> The opAssign kills all type safety. I think only NotNull!T should be accepted... So "foo = bar" won't compile if bar is nullable. To fix, "foo = NotNull(bar)",

I think NotNull also needs this, as a workaround to what I think is a DMD bug:

    @disable enum init = 0;

It disallows code like:
auto f1 = NotNull!Foo.init;

And I think NotNull needs a guard, to refuse std.typecons.Nullable:

struct NotNull(T) if (!IsNullable!T) {...

Where the IsNullable template is similar to std.typecons.isTuple (I think std.typecons needs a isTemplateInstance(T,Template)).

Bye,
bearophile
March 06, 2012
Adam D. Ruppe:

> I've trained myself to use assert (or functions with assert in out contracts/invariants) a lot to counter these.

I think contracts are better left to higher level ideas. The simple not-null contracts you are adding are better left to a type system that manages a succinct not-null syntax.

Bye,
bearophile
March 06, 2012
On 2012-03-05 22:31:34 +0000, "Steven Schveighoffer" <schveiguy@yahoo.com> said:

> On Mon, 05 Mar 2012 05:38:20 -0500, Walter Bright  <newshound2@digitalmars.com> wrote:
> 
>> I don't get this at all. I find it trivial to run the program with a  debugger:
>> 
>>    gdb foo
>>    >run
>> 
>> that's it.
> 
> This argument continually irks me to no end.  It seems like the trusty  (rusty?) sword you always pull out when defending the current behavior,  but it falls flat on its face when a programmer is faced with a Seg Fault  that has occurred on a program that was running for several days/weeks,  possibly not in his development environment, and now he must run it via a  debugger to wait another several days/weeks to (hopefully) get the same  error.
> 
> Please stop using this argument, it's only valid on trivial bugs that  crash immediately during development.

Walter's argument about using gdb doesn't make sense in many scenarios. He's probably used a little too much to programs which are short lived and have easily reproducible inputs (like compilers).

That said, throwing an exception might not be a better response all the time. On my operating system (Mac OS X) when a program crashes I get a nice crash log with the date, a stack trace for each thread with named functions, the list of all loaded libraries, and the list of VM regions dumped into ~/Library/Logs/CrashReporter/. That's very useful when you have a customer experiencing a crash with your software, as you can ask for the crash log. Can't you do the same on other operating systems?

Whereas if an exception is thrown without it being catched I get a stack trace on the console and nothing else, which is both less informative an easier to lose than a crash log sitting there on the disk.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

March 06, 2012
On Mon, 05 Mar 2012 20:17:32 -0500, Michel Fortin <michel.fortin@michelf.com> wrote:

>
> That said, throwing an exception might not be a better response all the time. On my operating system (Mac OS X) when a program crashes I get a nice crash log with the date, a stack trace for each thread with named functions, the list of all loaded libraries, and the list of VM regions dumped into ~/Library/Logs/CrashReporter/. That's very useful when you have a customer experiencing a crash with your software, as you can ask for the crash log. Can't you do the same on other operating systems?

It depends on the OS facilities and the installed libraries for such features.  It's eminently possible, and I think on Windows, you can catch such exceptions too in external programs to do the same sort of dumping.  On Linux, you get a "Segmentation Fault" message (or nothing if you have no terminal showing the output), and the program goes away.  That's the default behavior.  I think it's better in any case to do *something* other than just print "Segmentation Fault" by default.  If someone has a way to hook this in a better fashion, we can include that, but I hazard to guess it will not be on stock Linux boxes.

> Whereas if an exception is thrown without it being catched I get a stack trace on the console and nothing else, which is both less informative an easier to lose than a crash log sitting there on the disk.

Certainly for Mac OS X, it should do the most informative appropriate thing for the OS it's running on.  Does the above happen for D programs currently on Mac OS X?

Also, I don't think an exception is the right thing in any case -- it may not actually get caught if the Seg Fault is due to memory issues.  I'd rather the program do it's best attempt to print a stack trace and then abort.

-Steve
March 06, 2012
On Monday, March 05, 2012 21:04:20 Steven Schveighoffer wrote:
> On Mon, 05 Mar 2012 20:17:32 -0500, Michel Fortin
> 
> <michel.fortin@michelf.com> wrote:
> > That said, throwing an exception might not be a better response all the time. On my operating system (Mac OS X) when a program crashes I get a nice crash log with the date, a stack trace for each thread with named functions, the list of all loaded libraries, and the list of VM regions dumped into ~/Library/Logs/CrashReporter/. That's very useful when you have a customer experiencing a crash with your software, as you can ask for the crash log. Can't you do the same on other operating systems?
> 
> It depends on the OS facilities and the installed libraries for such features.  It's eminently possible, and I think on Windows, you can catch such exceptions too in external programs to do the same sort of dumping. On Linux, you get a "Segmentation Fault" message (or nothing if you have no terminal showing the output), and the program goes away.  That's the default behavior.  I think it's better in any case to do *something* other than just print "Segmentation Fault" by default.  If someone has a way to hook this in a better fashion, we can include that, but I hazard to guess it will not be on stock Linux boxes.

All you have to do is add a signal handler which handles SIGSEV and have it print out a stacktrace. It's pretty easy to do. It _is_ the sort of thing that programs may want to override (to handle other signals), so I'm not quite sure what the best way to handle that is without causing problems for them (e.g. initialization order could affect which handler is added last and is therefore the one used). Maybe a function should be added to druntime which wraps the glibc function so that programs can add their signal handler through _it_, and if that happens, the default one won't be used.

Regardless, I'm not sure whether the functions involved are POSIX or not, so I don't know whether it'll work on anything besides Linux. It would still be of benefit even if it were Linux-only though.

- Jonathan M Davis
March 06, 2012
On Mon, 05 Mar 2012 23:31:34 +0100, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> On Mon, 05 Mar 2012 05:38:20 -0500, Walter Bright <newshound2@digitalmars.com> wrote:
>
>> On 3/4/2012 11:50 PM, Chad J wrote:
>>> Problems:
>>> - I have to rerun the program in a debugger to see the stack trace. This is a
>>> slow workflow. It's a big improvement if the segfault is hard to find, but only
>>> a small improvement if the segfault is easy to find. Very bad if I'm prototyping
>>> experimental code and I have a bunch to go through.
>>
>> I don't get this at all. I find it trivial to run the program with a debugger:
>>
>>    gdb foo
>>    >run
>>
>> that's it.
>
> This argument continually irks me to no end.  It seems like the trusty (rusty?) sword you always pull out when defending the current behavior, but it falls flat on its face when a programmer is faced with a Seg Fault that has occurred on a program that was running for several days/weeks, possibly not in his development environment, and now he must run it via a debugger to wait another several days/weeks to (hopefully) get the same error.
>
> Please stop using this argument, it's only valid on trivial bugs that crash immediately during development.
>
> I wholeheartedly agree that we should use the hardware features that we are given, and that NullPointerException is not worth the bloat.  But we should be doing *something* better than just printing "Segmentation Fault".
>
> -Steve

There are two independent discussions being conflated here. One about getting more
information out of crashes even in release mode and the other about
adding runtime checks to prevent crashing merely in debug builds.