796 – Asserting a null object reference throws AssertError Failure internal\invariant.d(14) or Access Violation

D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 796 - Asserting a null object reference throws AssertError Failure internal\invariant.d(14) or Access Violation
Summary: Asserting a null object reference throws AssertError Failure internal\invaria...
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: Walter Bright
URL:
Keywords: patch, wrong-code
: 6913 (view as issue list)
Depends on:
Blocks:
Reported: 2007年01月05日 06:15 UTC by Lionello Lunesu
Modified: 2015年06月09日 05:11 UTC (History)
7 users (show)

See Also:


Attachments
Add an attachment (proposed patch, testcase, etc.)

Note You need to log in before you can comment on or make changes to this issue.
Description Lionello Lunesu 2007年01月05日 06:15:53 UTC
The following code causes a run-time assertion failure in internal\invariant.d(14) when linked against a debug build of Phobos (-unittest -g -w):
#class Class {}
#void main(){
# Class c;
# assert(c);
#}
It causes a run-time Access Violation when linked against the release build of Phobos.
Comment 1 Frits van Bommel 2007年01月05日 08:48:35 UTC
It seems to be according to the spec though.
I just looked it up, and assert(object) checks object's invariant; not just that it isn't null (that's assert(object !is null) apparently).
Not what I would've expected...
This isn't exactly clearly noted: this is mentioned on http://www.digitalmars.com/d/class.html#invariants but not http://www.digitalmars.com/d/expression.html#AssertExpression where it would be expected (especially since you wouldn't normally look at the section on invariants when figuring out what an assert does).
So maybe this should be noted there too (especially since every other use of objects in boolean context is a null check AFAIK). I've already added it to the comments page for that page.
The invariant checking routine in the runtime does perform an assert(o !is null), but that only gets compiled into a non-release build of Phobos.
In a release build it instead segfaults trying to look up the vtable of the object. (to get classinfo)
Comment 2 Lionello Lunesu 2007年01月06日 02:54:04 UTC
Nice catch! I never would have thought of that.
In any case, the assertion failure / access violation can be easily fixed if the compiler where to add a null-pointer check prior to checking the invariants. Frankly, I think this makes sense too. We can expect many C/C++ people doing "assert(instance)" only to check the pointer. If it were to check both the pointer and the invariants, that would just make it even more useful.
AFAIK, this cannot be changed by adding a check to invariant.d, since that would add unnecessary overhead to all invariant checks. The code generation for assert(instance) should be changed to include a pointer check: the assertion should fail for null-pointers:
assert(classref) 
// =>
assert( (classref !is null) && _d_invariant(classref) );
Comment 3 Frits van Bommel 2007年01月11日 04:13:27 UTC
It seems I misread the spec: it says the invariant *can* be checked on assert(classref), not that it *will* be. So the spec's fine.
The bug seems to be in the compiler.
Comment 4 Stewart Gordon 2007年01月11日 09:04:37 UTC
Indeed,
 assert(classref)
should be translated inline to
 assert((classref !is null) && _d_invariant(classref));
so that the error location is preserved.
Comment 5 torhu 2007年04月12日 18:55:55 UTC
I think the assert feature would be more intuitive if assert(obj) would only check for a null reference. That's what people expect it to do, and that's what they use it for most of the time. But doing both kinds of checks would be better than the current behavior.
If you really wanted to check the invariant explicitly, the syntax could be 'obj.invariant', 'invariant(obj)' or similar. This could be useful in the class' own methods, where there's no need to check for a null reference anyway.
Comment 6 Andrei Alexandrescu 2010年11月26日 14:13:26 UTC
Still present in 2.050.
Comment 7 Bernard Helyer 2011年03月07日 03:12:41 UTC
Every time I write 
 assert(object);
A dagger pierces my heart and I remember I must write
 
 assert(object !is null); 
Could we get this fixed this decade some time?
Comment 8 Stewart Gordon 2011年03月07日 04:17:53 UTC
(In reply to comment #7)
> Every time I write 
> 
> assert(object);
> 
> A dagger pierces my heart and I remember I must write
> 
> assert(object !is null); 
> 
> Could we get this fixed this decade some time?
Indeed. The intended behaviour (check that object is non-null AND satisfies its invariants) needs to be built into the compiler, not delegated to the RTL.
Comment 9 Mike Shulman 2011年05月31日 13:45:01 UTC
FYI: As a new D programmer, I found the segfault produced by this sort of code very confusing, and spent almost an hour trying to figure out where the issue in my code was and why I wasn't just getting an AssertError. Only when I found this bug report did I have any idea what was going on.
Comment 10 yebblies 2011年08月30日 10:17:34 UTC
https://github.com/D-Programming-Language/dmd/pull/358 
Comment 11 Alex Rønne Petersen 2011年11月08日 15:04:55 UTC
(In reply to comment #10)
> https://github.com/D-Programming-Language/dmd/pull/358 
+1 to this pull req from me.
Comment 12 yebblies 2011年11月08日 17:37:10 UTC
*** Issue 6913 has been marked as a duplicate of this issue. ***


AltStyle によって変換されたページ (->オリジナル) /