13

C++のアプリケーションでboost::shared_ptrを使用しています。メモリの問題は非常に深刻であり、アプリケーションは大量のメモリを消費します。

ただし、すべての新しいオブジェクトをshared_ptrに配置したため、アプリケーションが終了しても、メモリリークは検出できません。

std::vector<shared_ptr<> >リソースを保持しているプールのようなものが必要です。デバッグ時に、誰がshared_ptrを保持しているかを知るにはどうすればよいですか?

コードを1行ずつ確認するのは困難です。コードが多すぎます...

どうもありがとう!

4

8 に答える 8

22

shared_ptr「兄弟ポインタ」がどこにあるかを見るだけではわかりません。他のメソッドの中でも、 1 つが であるかどうかをテストunique()したり、取得したりできます。use_count()

于 2009-06-30T04:03:10.193 に答える
12

shared_ptrの一般的な広範な使用は、ほとんど必然的に、望ましくない、目に見えないメモリ占有を引き起こします。

循環参照はよく知られている原因であり、それらのいくつかは間接的であり、特に複数のプログラマーが作業する複雑なコードでは見つけるのが難しい場合があります。プログラマーは、クイックフィックスとして、あるオブジェクトが別のオブジェクトへの参照を必要とし、サイクルを閉じているかどうかを確認するためにすべてのコードを調べる時間がないと判断する場合があります。この危険は非常に過小評価されています。

あまりよく理解されていないのは、リリースされていない参照の問題です。オブジェクトが多くのshared_ptrsに共有されている場合、それらのすべてがゼロになるかスコープから外れるまで、オブジェクトは破棄されません。これらの参照の1つを見落としがちで、終了したと思っていたオブジェクトがメモリに潜んでいることになります。

厳密に言えば、これらはメモリリークではありませんが(プログラムが終了する前にすべて解放されます)、同様に有害であり、検出が困難です。

これらの問題は、適切な誤った宣言の結果です。1.共有された単一所有権として本当になりたいものを宣言します。scoped_ptrは正しいですが、そのオブジェクトへの他の参照は生のポインターである必要があり、ぶら下がっている可能性があります。2.パッシブ監視参照になりたいものをshared_ptrとして宣言します。weak_ptrは正しいでしょうが、それを使用するたびにそれをshare_ptrに変換する手間がかかります。

あなたのプロジェクトは、この慣習があなたを巻き込む可能性のある種類の問題の良い例だと思います。

メモリを大量に消費するアプリケーションを使用している場合は、デザインがオブジェクトの有効期間を明示的に制御できるように、単一の所有権が本当に必要です。

単一所有権の場合opObject=NULL; 間違いなくオブジェクトを削除し、今それを行います。

共有所有権の場合spObject=NULL; ........知るか?......

于 2009-08-07T08:15:53.767 に答える
7

ダングリングまたは循環スマート ポインター参照に対する解決策の 1 つは、スマート ポインター クラスをカスタマイズして、デバッグ専用のブックキーピング関数を追加することです。スマートポインターがオブジェクトへの参照を追加するたびに、スタック トレースを取得し、各エントリが追跡するマップに配置します。

  1. 割り当てられているオブジェクトのアドレス (ポインターが指すもの)
  2. オブジェクトへの参照を保持する各 smartpointer オブジェクトのアドレス
  3. 各スマートポインターが構築されたときの対応するスタックトレース

smartpointer が範囲外になると、マップ内のエントリが削除されます。オブジェクトへの最後の smartpointer が破棄されると、pointee オブジェクトはマップ内のエントリを削除されます。

次に、2 つの機能を備えた「リークの追跡」コマンドがあります。「[re]start leak tracking」(マップ全体をクリアし、まだ追跡されていない場合は追跡を有効にします) と「print open references」。作成されたすべての未解決のスマートポインター参照を表示します。 「漏れの追跡を開始する」コマンドが発行されたためです。これらのスマート ポインターが作成された場所のスタック トレースを確認できるため、オブジェクトが解放されないようにしているユーザーを簡単に正確に知ることができます。オンにすると速度が低下するため、常にオンのままにしておくことはありません。

実装するのはかなりの作業量ですが、これが頻繁に発生するコードベースを持っている場合は、間違いなく価値があります。

于 2013-02-28T09:22:38.873 に答える
4

サイクルを介した共有ポインタのメモリリークが発生している可能性があります。何が起こるかというと、共有オブジェクトは他の共有オブジェクトへの参照を保持し、最終的には元のオブジェクトに戻る可能性があります。これが発生すると、他の誰もオブジェクトにアクセスできない場合でも、サイクルはすべての参照カウントを1に保ちます。解決策は弱いポインタです。

于 2009-06-30T05:16:26.647 に答える
3

コードの一部をリファクタリングして、いくつかの場所で共有ポインターの代わりに弱いポインターを使用して所有権をより明示的に表現するようにしてください。

クラス階層を見ると、どのクラスが実際に共有ポインターを保持する必要があり、どのクラスが弱いポインターのみを必要とするかを判断することができます。 owner」オブジェクトはすでになくなっているはずです。一部のオブジェクトがポインターを失うのが早すぎることが判明した場合は、アプリ内のオブジェクト破壊シーケンスを調べて修正する必要があります。

于 2009-06-30T05:54:10.217 に答える
1

明らかに、アプリケーション内のオブジェクトへの参照を保持しています。これは、意図的に物事を記憶に留めていることを意味します。つまり、メモリリークはありません。メモリ リークは、メモリが割り当てられたときに、そのアドレスへの参照を保持しない場合に発生します。

基本的に、設計を見て、メモリ内に非常に多くのオブジェクトとデータを保持している理由と、それを最小限に抑える方法を理解する必要があります。

疑似メモリ リークが発生している 1 つの可能性は、自分が思っているよりも多くのオブジェクトを作成していることです。「new」を含むすべてのステートメントにブレークポイントを設定してみてください。アプリケーションが想定よりも多くのオブジェクトを構築しているかどうかを確認し、そのコードを読んでください。

この問題は実際にはメモリ リークではなく、アプリケーションの設計の問題です。

于 2009-06-30T04:02:03.283 に答える
1

Windows を使用している場合は、UMDH を使用することをお勧めします。これは非常に強力なツールです。それを使用して、解放されると予想されるトランザクション/期間ごとの割り当てを見つけ、誰がそれらを保持しているかを見つけます。

このSO回答に関する詳細情報があります スマートポインターによって引き起こされるメモリリークを見つける

于 2009-08-07T09:29:29.407 に答える