0

基本的な AddRef と Release を使用して参照カウントされる独自のスマート ポインター クラスがあります。

デバッグ中に、多くのオブジェクトが適切にリリースされていないことがわかります。どのオブジェクトが解放されていないかはわかりますが、それらがどの場所から割り当てられているかを見つけるのは困難です。

この問題に対処するための適切な設計パターンはありますか?

デバッグ ステートメントと ADDREF および RELEASE を配置し、 release が呼び出されたときに参照カウントを確認できます。場合によっては、1 を超える場合があります。これは、ポインターが削除されていないことを意味します。

shared_ptr const にブレークポイントを配置し始めると、何百回も呼び出され、メモリ リークを特定するのが難しくなります。

これらのリークの原因となっているいくつかの循環参照が作成されているようです。

4

2 に答える 2

2

これにはデザインパターンを使用しないでください。リークを検出するためだけにコードを肥大化させないでください。

メモリ ツールを使用します。Valgrind が頭に浮かび、Windows 用の商用のものも数多くあります。

また...

どのオブジェクトが解放されていないかはわかりますが、それらがどの場所から割り当てられているかを見つけるのは困難です。

なんで?オブジェクトのコンストラクターにブレークポイントを設定します。または、代わりに標準のポインター ( std::shared_ptrstd::unique_ptr) を使用します。

あなたの編集によると:

デバッグ ステートメントと ADDREF および RELEASE を配置し、 release が呼び出されたときに参照カウントを確認できます。場合によっては、1 を超える場合があります。これは、ポインターが削除されていないことを意味します。

コピー省略 (RVO/NRVO) を考慮していますか? これが原因の可能性が高いようです。

于 2012-10-09T17:39:03.290 に答える
1

数年前、auto_ptrコードベースで広く使用する独自のスマート ポインター クラスを作成しました。もちろん、バグだらけでした。

私はまったく同じ問題を抱えていました。リソース リークが発生した呼び出しサイトを特定するために使用した実際のコードをお見せすることはできませんが (コードはもう存在しないため)、何をしたかはお伝えできます。

最初に、ここ#defineで概説したものと同様のマクロ >SHUDDER< を作成しました。これは、オブジェクトを割り当てる代わりに使用できます。マクロは、追加のパラメーターをスマート ポインターに送信し、呼び出しサイトのファイルと行番号を示します。スマート ポインターはこれを保持します。new

次に、この機能をオンにnewするという魔法の呪文を唱えたときに、グローバルをマクロに置き換えました。明らかに、これはすべてのリリース ビルドで無効にする必要があり、実際にこれ#definesをデバッグしているときにデバッグ ビルドでのみ使用する必要があります。

次に、すべての呼び出しサイトを確認したいところまで、プログラムを実行させました。dump_call_sites()そこのスマート ポインターでメソッドを実行するとstatic vector、呼び出しサイトの文字列が stdout にダンプされます。問題が見つかったので、魔法の呪文をすべて元に戻して、このホクスポクスをすべてオフにしました。

これはまさにハックアンドスラッシュコーディングです。それはエレガントとはほど遠いものであり、独自の問題をもたらします。printfしかし、デバッグとともに、それはその場所を持っています。Rational Purify または Bounds Checker タイプの製品をロードする努力をしたくない、または実行できない場合、これは、リークがどこから来ているのかを素早く特定するのに役立ちます。

于 2012-10-09T18:23:26.560 に答える