On 05-Jul-17 12:11 AM, Christiano wrote:
> The book PPP2[1] presents the following code, Page 620 (2nd edition,
> fourth print):
>
> Link* Link::insert(Link* n) // insert n before this object; return n
> {
> if (n==nullptr) return this;
> if (this==nullptr) return n;
Looks like a typo.
It could be a thinko from habit, though, because when Bjarne designed
the language it didn't have exceptions, so the way to signal
construction failure was to do `this = 0;`. So at that time, before
exceptions, the `this` pointer could certainly be 0.
As I recall we got exception around 1989-1991, the time of the ARM.
> n–>succ = this; // this object comes after n
> if (prev) prev–>succ = n;
> n–>prev = prev; // this object’s predecessor
> becomes n’s predecessor
> prev = n; // n becomes this object’s
> predecessor
> return n;
> }
>
> What interested me in this code was exactly this part:
>
> if (this==nullptr) return n;
>
> So I searched about "null comparing this" using search engine.
>
> This website..
>
https://www.viva64.com/en/b/0226/
> ...says:
> "First of all according to the C++ standard (it follows from the
> paragraph 5.2.5/3 of the standard ISO/IEC 14882:2003(E)), calling any
> nonstatic method of any class through a null-pointer leads to undefined
> behavior. "
Right.
> But the ISO/IEC 14882:2003, § 5.2.5.3 says: If E1 has the type
> “pointer to class X,” then the expression E1->E2 is converted to the
> equivalent form (*(E1)).E2;
There is an infamous note (notes are non-normative in ISO standards) in
C++14 §8.3.2/5 (or C++98 §8.3.2/4): “in particular, a null reference
cannot exist in a well-defined program, because the only way to create
such a reference would be to bind it to the “object” obtained by
indirection through a null pointer, which causes undefined behavior”
It's infamous because it /claims/ that the standard elsewhere prescribes
UB for *p when p is a null pointer, but there is no such wording.
Still, everyone agrees that it's UB to dereference a nullpointer, except
in a `typeid` expression, where you're guaranteed an exception in that case.
> the remainder of 5.2.5 will address only
> the first option (dot) [59] . Abbreviating object-
> expression.id-expression as E1.E2, then the type and lvalue
> properties of this expression are determined as follows. In the
> remainder of 5.2.5, cq represents either const or the absence of
> const; vq represents either volatile or the absence of volatile. cv
> represents an arbitrary set of cv-qualifiers, as defined in 3.9.3.
> [59] Note that if E1 has the type “pointer to class X”, then (*(E1))
> is an lvalue.
>
> That is, the standard does not say exactly "calling any nonstatic method
> of any class through a null-pointer leads to undefined behavior".
> And (*(E1)) being a lvalue when E1 is null is not a problem IF THE
> PROGRAMMER IS AWARE OF WHAT HE IS DOING.
The compiler is free to insert code that checks for nullpointer and if
so, plants some nasty NSA malware on your computer.
> What I'm trying to say is exactly:
>
> The "Comparing 'this' Pointer to Null as an undefined
> behavior" is a MYTH which is not based on Standard.
No, not a myth, but the standard has never been fixed. It /claims/, in
non-normative text, that it says, but it doesn't actually say. That this
state of affairs has lasted through three and now soon four revisions is
pretty weird, but presumably more important stuff's been fixed instead.
No, that code is just a typo or thinko.
> g++ is correct [2], and Clang is correct [3].
Yes, UB means that they can do whatever. So I haven't even checked what
you cite that they do. Or don't.
> And the standard shouldn't forbid it because it has been used correctly
> for a long time without problems so that it would be much fairer to be
> interpreted as a technique.
It was used for a long time – before C++ got exceptions.
Which was roughly 10 years before the first standardization.
[snip]
Cheers & hth.,
- Alf