assert(obj) is an atrocity

Timon Gehr timon.gehr at gmx.ch
Tue Nov 8 23:35:22 PST 2011


On 11/09/2011 01:46 AM, Martin Nowak wrote:
> On Wed, 09 Nov 2011 01:28:06 +0100, Timon Gehr <timon.gehr at gmx.ch> wrote:
>
>> On 11/09/2011 01:21 AM, Timon Gehr wrote:
>>> On 11/09/2011 01:18 AM, Martin Nowak wrote:
>>>> On Tue, 08 Nov 2011 23:35:33 +0100, Alex Rønne Petersen
>>>> <xtzgzorex at gmail.com> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> As the title suggests, I'm going to be rather blunt about this.
>>>>> assert(obj) testing the invariant *without* doing a null check is
>>>>> insane for the following reasons:
>>>>>
>>>>> 1) It is not what a user expects. It is *unintuitive*.
>>>>> 2) assert(!obj) does an is-null check. assert(obj) is a completely
>>>>> broken opposite of this.
>>>>> 3) No AssertError is thrown, which is the entire point of the built-in
>>>>> assert().
>>>>> 4) The few added instructions for the null check hardly matter in a
>>>>> *debug* build of all things.
>>>>>
>>>>> I don't mind assert(obj) testing the invariant of obj. In fact, that
>>>>> very much makes sense. But please, please, *please* check the object
>>>>> for null first. This is a random inconsistency in the language with no
>>>>> other justification than "seg faults are convenient in a debugger". By
>>>>> the same logic, we might as well not have array bounds checks.
>>>>> However, the state of things is that array bounds checks are emitted
>>>>> by default and users can disable them for e.g. a release build. I
>>>>> don't see why this case is any different.
>>>>>
>>>>> - Alex
>>>>
>>>> It does check for null.
>>>> Only it's a runtime support function (_d_invariant) and druntime is
>>>> likely
>>>> compiled without assertions. Are you really suggesting to add a null
>>>> check before
>>>> every method call?
>>>>
>>>> martin
>>>
>>> No, he is suggesting to add a null check for assert(objref);, a
>>> construct that *looks* as if it was a null check, but does something
>>> almost unrelated.
>>
>> BTW, the number of occurrences of assert(objref && 1); in my code is
>> huge.
>>
>>
>>
>
> Just as a side note.
> I personally consider this as harmful. All too often an assert(obj !is
> null) is misused
> as disclaimer. It pretends false safety, while the obscure case where
> something is called
> with null is not found during testing.

What exactly do you consider harmful? If a function cannot deal with 
null it cannot. I like to have an assertion failure during debugging 
rather than a segfault. There is no "false safety", or
"true safety" for that matter, it is just as safe as not asserting 
before dereferencing the null pointer.

//...
this(Class cc)in{assert(cc&&1);}body{c=cc;}
invariant(){ assert(c&&1); }

void foo(){/* rely on c !is null. */}
//...

(Btw, I tried to verify my statement, but actually there were only about 
30 of those asserts in >6000 LOC.)

> It also creates a coupling of the caller and the callee, because not
> calling something with null
> is now part of the in contract.

You make it sound like that is a bad thing?






More information about the Digitalmars-d mailing list