First of all, I'm aware that calling a method on a null pointer is undefined behavior. I also know that, because this is not supposed to happen, compilers can (and do) assume this
to always be non-null.
But in real code, you sometimes do it accidentially. Usually, it has no ill effects, except that of course this
is null in the method, and things may crash.
As a debugging aid, and in the spirit of crash-early, I put assert(this != 0)
in a method that I accidentially called on null pointers a couple of times before. It seems to work, but clang complains with:
warning: 'this' pointer cannot be null in well-defined C++ code; comparison may be
assumed to always evaluate to true [-Wtautological-undefined-compare]
assert (this ! = 0);
^~~~ ~
I wonder what the best (least incorrect) way would be to detect that this
is null. A simple comparison could be optimized out.
this
to try and fool the compiler, or force it to treat the pointer as an integer.memcmp
.One additional concern is that, in case of inheritance, the "null" this pointer might actually be something like 0x00000004
, so it would be nice to also handle that case. I'm interested in a solution for either Clang, MSVC, or GCC.
Typically, you'll check for null using the triple equality operator ( === or !== ), also known as the strict equality operator, to be sure that the value in question is definitely not null: object !== null . That code checks that the variable object does not have the value null .
It is a good idea to check for null explicitly because: You can catch the error earlier. You can provide a more descriptive error message.
If you have implemented layering in your project, good place to do null checks are the layers that receives data externally. Like for example: the controllers, because it receives data from the user... or the gateways because it receives data from repositories.
Checking for null values and initializing them is a necessary step in the implementation of a ruleset, because input objects might be null or contain null values. Objects used in the rules are either input parameter objects or objects that have been inserted in the working memory.
In gcc you can build with -fsanitize=null
. Clang should have this option as well.
From man gcc
:
-fsanitize=null
This option enables pointer checking. Particularly, the application built with this option turned on will issue an error message when it tries to dereference a NULL pointer, or if a
reference (possibly an rvalue reference) is bound to a NULL pointer, or if a method is invoked on an object pointed by a NULL pointer.
Here is a test program:
[ ~]$ cat 40783056.cpp
struct A {
void f() {}
};
int main() {
A* a = nullptr;
a->f();
}
[ ~]$ g++ -fsanitize=null 40783056.cpp
[ ~]$
[ ~]$ ./a.out
40783056.cpp:7:7: runtime error: member call on null pointer of type 'struct A'
First of all, as pointed out by the comments to this question: do try using sanitizers built into the compilers.
To answer your question: you can cast your pointer to uintptr_t
and compare that value. Please note that this conversion is implementation defined and is not guaranteed to work as you expected.
The following code optimizes nothing out with clang 3.9, but removes null pointer check with gcc 7.0. 0x10
has been chosen arbitrarily.
struct foo
{
void bar() {
if(this == nullptr) {
sink(__LINE__);
}
if((uintptr_t)this < 0x10) {
sink(__LINE__);
}
if((volatile uintptr_t)this < 0x10) {
sink(__LINE__);
}
}
};
demo
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