This code :
int *p = nullptr;
p++;
cause undefined behaviour as it was discussed in Is incrementing a null pointer well-defined?
But when explaining fellows why they should avoid UB, besides saying it is bad because UB means that anything could happen, I like to have some example demonstating it. I have tons of them for access to an array past the limits but I could not find a single one for that.
I even tried
int testptr(int *p) {
intptr_t ip;
int *p2 = p + 1;
ip = (intptr_t) p2;
if (p == nullptr) {
ip *= 2;
}
else {
ip *= -2;
} return (int) ip;
}
in a separate compilation unit hoping that an optimizing compiler would skip the test because when p
is null, line int *p2 = p + 1;
is UB, and compilers are allowed to assume that code does not contain UB.
But gcc 4.8.2 (I have no useable gcc 4.9) and clang 3.4.1 both answer a positive value !
Could someone suggest some more clever code or another optimizing compiler to exhibit a problem when incrementing a null pointer ?
How about this example:
int main(int argc, char* argv[])
{
int a[] = { 111, 222 };
int *p = (argc > 1) ? &a[0] : nullptr;
p++;
p--;
return (p == nullptr);
}
At face value, this code says: 'If there are any command line arguments, initialise p
to point to the first member of a[]
, otherwise initialise it to null. Then increment it, then decrement it, and tell me if it's null.'
On the face of it this should return '0' (indicating p
is non-null) if we supply a command line argument, and '1' (indicating null) if we don't.
Note that at no point do we dereference p
, and if we supply an argument then p
always points within the bounds of a[]
.
Compiling with the command line clang -S --std=c++11 -O2 nulltest.cpp
(Cygwin clang 3.5.1) yields the following generated code:
.text
.def main;
.scl 2;
.type 32;
.endef
.globl main
.align 16, 0x90
main: # @main
.Ltmp0:
.seh_proc main
# BB#0:
pushq %rbp
.Ltmp1:
.seh_pushreg 5
movq %rsp, %rbp
.Ltmp2:
.seh_setframe 5, 0
.Ltmp3:
.seh_endprologue
callq __main
xorl %eax, %eax
popq %rbp
retq
.Leh_func_end0:
.Ltmp4:
.seh_endproc
This code says 'return 0'. It doesn't even bother to check the number of command line args.
(And interestingly, commenting out the decrement has no effect on the generated code.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With