In my daily work I usually
use C# however there is some interactions with C++ in the legacy
code. Recently a change woke an dormant bug which took a while to
track down due to some misdirection.
A simplified but similar
error is displayed in this code.
#include <iostream>
#include <list>
using namespace std;
class A {
private:
list<int> IntegerList;
public:
int getListCount() {
return IntegerList.size();
}
};
class B {
public:
A* AClass;
};
int main() {
B* BClass = new B();
if (BClass) {
cout << BClass->AClass->getListCount() << endl;
}
return 0;
}
Member function of classes
are about the same thing as usual free functions, they just hide that
they require a this pointer to the object calling them as their first
argument. This pointer can be null which means that the code does not
crash when you call a member function on an uninitialized class
instance. The crash first occurs when you try to work with the
non-existing memory that you think your class contains.
You always want to crash
early when a problem occurs, this simplifies the location of the
problem. In the code above the crash does not occur until we try to
get the size of the integer list. This problem could have easily been
avoided with some defensive programming and RIIA.
In the code below I have
made sure that the AClass gets assigned when the BClass gets
created and even though I'm pretty certain AClass now exists an
assert will make sure we crash at a more logical position in the
code.
#include <iostream>
#include <list>
#include <cassert>
using namespace std;
class A {
private:
list<int> IntegerList;
public:
int getListCount() {
return IntegerList.size();
}
};
class B {
public:
B() : AClass(new A()) {}
virtual ~B() { delete AClass; }
A* AClass;
};
int main() {
B* BClass = new B();
if (BClass) {
assert(BClass->AClass != NULL);
cout << BClass->AClass->getListCount() << endl;
}
return 0;
}
No comments:
Post a Comment