I believe I've found a bug in the implementation of the "==" operator for pointers in both gcc and clang.
pointer_equality_bug.c
is a demonstration of the bug.
Quoting N1570 6.5.9p6:
Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.
with a footnote:
Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. If prior invalid pointer operations (such as accesses outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined behavior.
I posted the initial version of the demo program to comp.lang.c on
Sun 2014-10-19, Message-ID: <[email protected]>
.
A Google Groups link to the original article is
here.
Thomas Richter pointed out that the quoted clause applies only to array
objects, and the original version of the test program uses non-array
int
objects. The standard says, in 6.5.9p7, that:
For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
But to avoid any ambiguity, I've updated the program to use explicit array objects, and the problem still exists.
Compiling with -S
to generate an assembly listing shows that no
code is generated for the puts("ok")
call, implying that this is
an optimization bug that occurs even with no optimization specified
(equivalent to -O0
).
If my interpretation is correct, and this is a compiler bug, I don't
think it's likely to affect real-world code. There's not much reason
to compare a pointer to one object vs. a pointer just past the end
of another object for equality. The relevant clause in the standard
is, I think, intended to make ==
behave consistently in all cases,
even ones that are not particularly useful.
Tue 2014-10-21
I've submitted bug reports against gcc:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63611
and clang:
http://llvm.org/bugs/show_bug.cgi?id=21327
Mon 2014-10-27 Tim Rentsch points out that N807, submitted by Clive D.W. Feather on 1997-12-27, discusses this. It refers to DR 172; I'll track that down and update this later.