web-dev-qa-db-ja.com

C ++でのオブジェクトの削除

ここに私が持っているサンプルコードがあります:

_void test()
{
   Object1 *obj = new Object1();
   .
   .
   .
   delete obj;
}
_

Visual Studioで実行すると、 'delete obj;'の行でクラッシュします。これは、オブジェクトに関連付けられたメモリを解放する通常の方法ではありませんか?デストラクタを自動的に起動することに気付きました...これは正常ですか?


コードスニペットは次のとおりです。

_    if(node->isleaf())
    {
        vector<string> vec = node->L;
        vec.Push_back(node->code);
        sort(vec.begin(), vec.end());

        Mesh* msh = loadLeaves(vec, node->code);

        Simplification smp(msh);

        smp.simplifyErrorBased(errorThreshold);

        int meshFaceCount = msh->faces.size();

        saveLeaves(vec, msh);

        delete msh;
    }
_

loadleaves()は、ディスクからメッシュを読み取り、Meshオブジェクトを作成して返す関数です。(vecおよび_node->code_は、開くファイル)

_delete msh;_行を削除する必要がありますか?

27
Nima

これは、オブジェクトに関連付けられたメモリを解放する通常の方法ではありませんか?

これは、動的に割り当てられたメモリを管理する一般的な方法ですが、そうするのは良い方法ではありません。この種のコードは例外セーフではないため脆弱です。オブジェクトの作成時と削除時の間に例外がスローされると、そのオブジェクトがリークします。

スコープにバインドされたリソース管理を取得するために使用できるスマートポインターコンテナーを使用する方がはるかに優れています(より一般的には、 リソースの取得は初期化 、またはRAIIと呼ばれます)。

自動リソース管理の例として:

void test()
{
    std::auto_ptr<Object1> obj1(new Object1);

} // The object is automatically deleted when the scope ends.

ユースケースによっては、auto_ptrが必要なセマンティクスを提供しない場合があります。その場合、shared_ptrの使用を検討できます。

オブジェクトを削除するときにプログラムがクラッシュする理由については、誰も確実にその質問に答えることができる十分なコードを与えていません。

37
James McNellis

あなたのコードは確かに通常の方法で動的オブジェクトを作成および削除しています。はい、deleteがコンストラクターを呼び出さなければならないように、newがオブジェクトのデストラクタを呼び出すことは完全に正常です(そして実際に言語標準で保証されています!)。

インスタンス化していない場合はObject1直接ではありますが、そのサブクラスの一部であるため、継承されるクラスにはvirtualデストラクタが必要であることに注意してください(正しいサブクラスのデストラクタは、これに類似したケースで呼び出すことができます) -しかし、サンプルコードが実際のコードを実際に代表している場合、これは現在の問題ではありえません-他の何か、おそらくあなたが私たちに見せていないデストラクタコード、またはコードのヒープ破損のいずれかでなければなりませんその関数またはそれが呼び出すものの中に表示されていない...?

ところで、インスタンス化する関数を終了する直前に常にオブジェクトを削除する場合、そのオブジェクトを動的にすることは意味がありません-ローカル(ストレージクラスauto、そのまま上記の関数のデフォルト)変数!

7
Alex Martelli

これは、オブジェクトに関連付けられたメモリを解放する通常の方法ではありませんか?

はい、そうです。

デストラクタを自動的に起動することに気付きました...これは正常ですか?

はい

double delete オブジェクトではなかったことを確認してください。

3
Prasoon Saurav

delete行でクラッシュした場合、ほぼ確実にヒープが破損しています。あなたが提示した例にはエラーがないため、問題を診断するためにより多くのコードを見る必要があります。

おそらく、ヒープにバッファオーバーフローが発生し、ヒープ構造が破損したり、「ダブルフリー」(またはC++の場合は「ダブルデリート」)のような単純なものが破損した可能性があります。

また、The Fuzzが述べたように、デストラクタにもエラーがある可能性があります。

そして、はい、それは完全に正常であり、deleteがデストラクタを呼び出すことが期待されています。これは実際には2つの目的の1つです(デストラクタを呼び出してからメモリを解放します)。

2
Evan Teran

saveLeaves(vec,msh);
mshポインターを取り、vecの内部に置くと仮定しています。 mshはメモリへのポインタにすぎないため、削除すると、ベクター内でも削除されます。

2
Brandon York