Today, I lost more than half a day debugging a bizarre issue in a C++ project.
The cause? A null pointer.
A piece of code that shouldn't work.
But it did.
Log* log = new Log("[TEXT] ");
log->print("Hello, World!"); // Works
log = nullptr;
log->print("Why does this work?"); // Still prints?!
log->printPrefix("This won't work");
delete log;
The print() method doesn't access any member variables, so the compiler can generate code that appears to work even though calling a non-static member function through a null pointer is undefined behaviour.
Meanwhile, the original object is leaking memory, and delete log does absolutely nothing because log is now nullptr.
And there goes half a day with lots of confusion. ðŸ«
The lesson
Just because your C++ code works doesn't mean it's correct nor makes sense. Undefined behavior doesn't promise to crash. Sometimes, it just quietly wastes your afternoon.
The complete code:
#include <iostream>
class Log {
private: std::string prefix;
public: void print(const std::string & message) {
std::cout << message << std::endl;
}
public: void printPrefix(const std::string & message) {
std::cout << prefix << message << std::endl;
}
Log(const std::string & p): prefix(p) {}
};
int main() {
Log * log = new Log("[TEXT] ");
log -> print("Hello, World!");
log -> printPrefix("Hello, World!");
log = nullptr;
log -> print("Why does this work?");
log -> printPrefix("Why does this work?");
delete log;
return 0;
}
Coverimage source: https://unsplash.com/de/fotos/eine-katze-schaut-in-die-kamera-L_jzNaicIIM
Top comments (0)