3

コードを分析していて、特定のコードについて混乱しています。同じ意味を伝えるコード/疑似コードを投稿しました。

クラス1

Class1::Func1()
{
    Collection* cltn;   
    try
    {
        cltn = Class2::get_records_from_db();
    }
    catch(Informix error)
    {}
    catch(DB Error)
    {}
    catch(...)
    { Unknown exception }          //I get this error always once the process processes lot of records   
}

クラス2

Collection* Class2::get_records_from_db()
{
    Collection *clt = new Collection();
    try
    {

        //Query database
        For each row in query result
        Row *row = new row();
        populate(row)
        clt->add(*row)

         ...
        if( Informix error)
        {
            throw Informix error;
        }  
     }

     catch(...)
     {
          delete clt;  //Who will delete row?
          clt = 0;
          throw Db error 
     }

    return clt;  //Who will delete clt?
}

問題 - パート 2

最初の問題についての洞察をありがとう。ここに、実際に起きている問題があります。

Class 1C++ プロセスでClass 2あり、Informix データベースと対話するライブラリです。 Class2::get_records_from_db()Informix DB にクエリを実行し、結果セットを返す関数です。上記のコードを拡張して、実際のコードにより近いものにしました。

Collectionobjects は 200k のオブジェクトを処理しrowますが、ほとんどの人が言ったように、適切にリリースされていません。
呼び出し元は、一般的なキャッチ ブロックで「不明な例外」を参照しています。で作成された巨大なメモリ リークが原因Class 2でしょうか。

406 (Out of memory error)ログにいくつかの Informix エラーも表示されます。Unknown Exception一連の&を吐き出した後、プロセスはコアダンプします。SQLERR406

コア ダンプがメモリ リークの副産物であるかどうかを知りたいです。

4

2 に答える 2

12

あなたが提示したコードの問題は何ですか?

あなたが提示するコード例は、非常に悪い、間違ったコードです。

row(とclt)のどちらも削除しません。これは、デストラクタの実装が自明か非自明かに応じて、メモリ リークまたは未定義の動作につながります。どちらにしても、非常に悪いことが起こる可能性があることを意味します。

を使用してオブジェクトを割り当てる場合は、によって返されたポインタnewを呼び出して、明示的に割り当てを解除する必要があります。どちらのポインターも呼び出さないため、両方とも割り当てが解除されることはありません。deletenewdelete

誰が削除の責任を負うべきですか?

オブジェクトそのもの!
オブジェクトには、scope( {, }) が終了するとすぐに割り当てを解除する機能が組み込まれている必要があります。この方法では、オブジェクトの割り当てを明示的に解除する必要はありませんが、不要になると暗黙的に削除されます。この手法は、C++のResource Allocation is Initialization (RAII) または Scope Bound Resource Management (SBRM)として広く知られています。

オブジェクト (rowおよびclt)のそれぞれは、これらの生のポインターにラッパーを書き込むことによってRAIIを使用する必要があります

于 2012-06-20T12:41:20.487 に答える
2

スマートポインターが必要です。ポインターの代わりにそれぞれの newRowを配置する必要があります。std::shared_ptr<Row> rowこれらshared_ptrの s は、範囲外になると自動的にクリーンアップされます (たとえば、try-catch ブロックが終了したとき)。

' で何をすべきかはcltそれほど明確ではありません...私はそれを a に保存してそれstd::unique_ptr<Collection>を返したいと思います。なぜなら、a) ある時点で自動的に削除されることが明らかだからですexit) および b)を生成したインスタンス (またはシングルトン)get_records_from_db()ではなく、によって返された値を所有していることは、呼び出し元のコードにとって明らかです。Class2

明確な所有権のセマンティクスは良いことです。

于 2012-06-20T12:46:56.283 に答える