I recently had the following memory bug, which is easy to spot here, but can be harder to detect in more complex code:
class Foo : public IFoo {
const Bar& bar_;
public:
Foo(const Bar& bar) : bar_(bar) {
}
void test() {
// access bar_ here
}
};
int baz() {
IFoo* foo = NULL;
if(whatever) {
Bar bar;
foo = new Foo(bar);
}
else {
// create other foo's
}
foo->test(); // segmentation fault
}
The bug is that Bar immediately goes out of scope, is destroyed and then used in foo->test(). One solution is to create Bar on the heap, using Bar* bar = new Bar(). However, I don't like to do this because I'd have to keep the Bar* bar pointer at top-level so I can access and delete it at the end, even though Bar is something that is specific to that particular code block if(whatever){}.
Another solution is boost::shared_ptr<Bar>, but I cannot just write this:
if(whatever) {
boost::shared_ptr<Bar> bar(new Bar());
foo = new Foo(*bar);
}
since the shared_ptr goes out of scope immediately, too, destroying the contained object.
So in short, to get rid of this problem, I'd have to use shared_ptr everywhere, in Foo as member variable, in Foo's constructor, etc. To eliminate these problems in general, all my APIs etc. have to use shared_ptr, which is kind of ugly. But, is it the right thing to do? So far, I have used it sometimes to create reference-counted objects, but I have kept my APIs clean of shared_ptr. How do you deal with this problem that, once you use shared_ptr you have to use it everywhere?
(Also, if you use these reference-counted pointers, you have to start worrying about if you really want shared_ptr or rather weak_ptr etc.)
And, what would I use as an equivalent to Foo(const Bar& bar)? Foo(const shared_ptr<const Bar> bar)?
Another option, of course, is to add reference counting inside the Bar and other objects yourself, using pimpl and your own counters, but that gets too tedious as a general rule.