dereferencing null
Steven Schveighoffer
schveiguy at yahoo.com
Wed Mar 7 04:57:41 PST 2012
On Mon, 05 Mar 2012 23:58:48 -0500, Chad J
<chadjoan at __spam.is.bad__gmail.com> wrote:
> On 03/05/2012 11:27 PM, Jonathan M Davis wrote:
>> On Tuesday, March 06, 2012 05:11:30 Martin Nowak wrote:
>>> 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.
>>
>> A segfault should _always_ terminate a program - as should
>> dereferencing a
>> null pointer. Those are fatal errors. If we had extra checks, they
>> would have
>> to result in NullPointerErrors, not NullPointerExceptions. It's horribly
>> broken to try and recover from dereferencing a null pointer. So, the
>> question
>> then becomes whether adding the checks and getting an Error thrown is
>> worth
>> doing as opposed to simply detecting it and printing out a stack trace.
>> And
>> throwing an Error is arguably _worse_, because it means that you can't
>> get a
>> useful core dump.
>>
>> Really, I think that checking for null when dereferencing is out of the
>> question. What we need is to detect it and print out a stacktrace. That
>> will
>> maximize the debug information without costing performance.
>>
>> - Jonathan M Davis
>
> Why is it fatal?
A segmentation fault indicates that a program tried to access memory that
is not available. Since the 0 page is never allocated, any null pointer
dereferencing results in a seg fault.
However, there are several causes of seg faults:
1. You forgot to initialize a variable.
2. Your memory has been corrupted, and some corrupted pointer now points
into no-mem land.
3. You are accessing memory that has been deallocated.
Only 1 is benign. 2 and 3 are fatal. Since you cannot know which of
these three happened, the only valid choice is to terminate.
I think the correct option is to print a stack trace, and abort the
program.
> I'd like to be able to catch these. I tend to run into a lot of fairly
> benign sources of these, and they should be try-caught so that the user
> doesn't get the boot unnecessarily. Unnecessary crashing can lose user
> data. Maybe a warning message is sufficient: "hey that last thing you
> did didn't turn out so well; please don't do that again." followed by
> some automatic emailing of admins. And the email would contain a nice
> stack trace with line numbers and stack values and... I can dream huh.
You cannot be sure if your program is in a sane state.
> I might be convinced that things like segfaults in the /general case/
> are fatal. It could be writing to memory outside the bounds of an array
> which is both not bounds-checked and may or may not live on the stack.
> Yuck, huh. But this is not the same as a null-dereference:
>
> Foo f = null;
> f.bar = 4; // This is exception worthy, yes,
> // but how does it affect unrelated parts of the program?
Again, this is a simple case. There is also this case:
Foo f = new Foo();
... // some code that corrupts f so that it is now null
f.bar = 4;
This is not a "continue execution" case, and cannot be distinguished from
the simple case by compiler or library code.
Philosophically, any null pointer access is a program error, not a user
error, and should not be considered for "normal" execution. Terminating
execution is the only right choice.
-Steve
More information about the Digitalmars-d
mailing list