最近、次のメモリ バグが発生しました。ここでは簡単に見つけることができますが、より複雑なコードでは検出が難しくなる可能性があります。
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
}
バグは、Bar
すぐに範囲外になり、破棄されてから で使用されることfoo->test()
です。Bar
1 つの解決策は、を使用してヒープ上に作成することBar* bar = new Bar()
です。ただし、特定のコードブロックに固有のものであっても、最後にBar* bar
アクセスできるようにポインターをトップレベルに保持する必要があるため、これを行うのは好きではありません。delete
Bar
if(whatever){}
別の解決策は ですがboost::shared_ptr<Bar>
、これだけを書くことはできません:
if(whatever) {
boost::shared_ptr<Bar> bar(new Bar());
foo = new Foo(*bar);
}
もすぐに範囲外になりshared_ptr
、含まれているオブジェクトが破棄されるためです。
要するに、この問題を取り除くには、どこでも、メンバー変数として、のコンストラクターなどを使用shared_ptr
する必要があります。これらの問題を一般的に解消するには、すべての API などで を使用する必要があります。醜い。しかし、それは正しいことですか?これまでのところ、参照カウント オブジェクトを作成するために時々使用してきましたが、API をクリーンな状態に保っています。一度使用すると、どこでも使用しなければならないというこの問題にどのように対処しますか?Foo
Foo
shared_ptr
shared_ptr
shared_ptr
(また、これらの参照カウント ポインターを使用する場合は、本当に必要shared_ptr
かどうかweak_ptr
などについて心配し始める必要があります。)
そして、私は何を同等のものとして使用しFoo(const Bar& bar)
ますか? Foo(const shared_ptr<const Bar> bar)
?
もちろん、別のオプションとして、Bar
および他のオブジェクト内に参照カウントを追加pimpl
し、独自のカウンターを使用することもできますが、一般的なルールとしては面倒です。