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.