Reputation: 493
The problem is that an implicit cast of nullptr, to the second super class, of a class with multiple inheritance results (at least with LLVM 7.0.2) in an adjustment being applied to the nullptr. The pointer is now no longer null which (if null checks are being performed in the methods of the super class) can result in a crash (I guess technically undefined behaviour).
Here's a minimal example:
#include <iostream>
inline bool pointerIsNotNull(const void* ptr) { return ptr != nullptr; }
class IntValue {
public:
IntValue() { }
int getIntValue() { return pointerIsNotNull(this) ? value : 0; }
private:
int value;
};
static const char* nullptrChar = "nullptr";
class CharValue {
public:
CharValue() { }
const char* getCharValue() { return pointerIsNotNull(this) ? value : nullptrChar; }
private:
char* value;
};
class Foo : public IntValue, public CharValue {
public:
Foo() { }
double getDoubleValue() { return pointerIsNotNull(this) ? value : 0; }
protected:
double value;
};
int main(int argc, const char * argv[])
{
Foo* foo = nullptr;
std::cout << foo->getIntValue() << std::endl;
CharValue* charValue = foo;
std::cout << charValue->getCharValue() << std::endl;
std::cout << foo->getCharValue() << std::endl;
}
My question is this: Is there a way to check for this kind of shenanigans without manually checking for nullptr before calls into a second superclass?
You know, is there an elegant way to do this (maybe in the second superclass) which would assure me that I've caught all possible examples of this behaviour?
EDIT: Yes, I know calling member functions from a nullptr isn't modern practice. I thought (until I posted this question) that it used to be accepted practice and in any case I'm constrained by standards I don't have control over. So, with the assumption that calling a member function on a nullptr will always enter the correct function, is there an elegant solution to my problem?
Upvotes: 2
Views: 152
Reputation: 66451
foo->getIntValue()
is undefined when foo
is the null pointer, which makes your entire program undefined.
That is, the dereferencing itself is undefined, and your program is doomed before it reaches the check.
There is no point in checking whether this
is null, since a compiler is free to assume that it isn't (if it were, the program would be undefined, so the compiler can do whatever it wants).
Upvotes: 6