1

悪いエラーが発生します。オブジェクト階層の最上位にあるオブジェクトに対してdeleteを呼び出すと(子オブジェクトが削除されることを期待して)、プログラムが終了し、次のようになります。

***glibcが検出されました***/home / mossen / worksheet / abbot / Debug / abbot:ダブルフリーまたは破損(出力):0xb7ec2158 ***

続いて、ある種のメモリダンプのように見えます。私はこのエラーを検索しましたが、私が収集したものから、すでに削除されているメモリを削除しようとすると発生するようです。この削除を試みるコードには1つの場所しかないため、不可能です。ここに奇妙な部分があります:それはデバッグモードでは発生しません。問題のコード:


Terrain::~Terrain()
{
    if (heightmap != NULL) // 'heightmap' is a Heightmap*
    {
        cout << "heightmap& == " << heightmap << endl;
        delete heightmap;
    }
}

ハイトマップデストラクタのすべてをコメントアウトしましたが、それでもこのエラーが発生します。エラーが発生した場合、

heightmap&== 0xb7ec2158

印刷されます。デバッグモードでは、コードをゆっくりとステップスルーできます。

heightmap&== 0x00000000

が印刷され、エラーはありません。'ハイトマップの削除;'をコメントアウトすると 行、エラーは発生しません。上記のデストラクタは、別のデストラクタから呼び出されます(個別のクラス、仮想デストラクタなどはありません)。ハイトマップポインタは、次のようなメソッドで新しく追加されました。


Heightmap* HeightmapLoader::load() // a static method
{
   // ....
   Heightmap* heightmap = new Heightmap();
   // ....other code
   return heightmap;
}

静的メソッドのスタックスペースで初期化されたポインタを返すことと関係があるのでしょうか?削除は正しく行っていますか?私がチェックしたり、より良くしたりできることに関する他のヒントはありますか?

4

4 に答える 4

2

load()呼び出されなかった場合はどうなりますか?クラスコンストラクタは初期化されますかheightmap、それともデストラクタに到達したときに初期化されていませんか?

また、あなたは言う:

...すでに削除されているメモリを削除します。この削除を試みるコードには1つの場所しかないため、不可能です。

ただし、プログラムの実行中にデストラクタが複数回呼び出される可能性があることを考慮していません。

于 2009-10-26T04:43:03.363 に答える
2

デバッグ モードでは、多くの場合、ポインタは NULL に設定され、メモリ ブロックはゼロになります。これが、デバッグ/リリース モードで異なる動作が発生する理由です。

従来のポインターの代わりにスマートポインターを使用することをお勧めします

auto_ptr<Heightmap> HeightmapLoader::load() // a static method
{
   // ....
   auto_ptr<Heightmap> heightmap( new Heightmap() );
   // ....other code
   return heightmap;
}

そうすれば、自動的に削除されるため、後で削除する必要はありません

boost::shared_ptrも参照してください

于 2009-10-26T04:45:56.307 に答える
1

その dtor を 2 回呼び出している可能性は十分にあります。デバッグ モードでは、ポインターはたまたま削除時にゼロになり、最適化モードではそのままになります。明確な解決策ではありませんが、頭に浮かぶ最初の回避策はheightmap = NULL;、削除の直後に設定することです。これは必要ではありませんが、Terrain インスタンスを破棄している理由の説明を探している間は問題ありません。 2 回!-) [[あなたが示しているわずかな量のコードには、二重破壊の理由を説明するのに役立つものはまったくありません。]]

于 2009-10-26T04:45:09.520 に答える
0

初期化されていないポインターの典型的なケースのように見えます。@Greg が言ったように、load() が Terrain から呼び出されない場合はどうなりますか? コンストラクターHeightMap*内でポインターを初期化していないと思います。Terrainデバッグ モードでは、このポインターを NULL に設定できます。C++ は、NULL ポインターの削除が有効な操作であるため、コードがクラッシュしないことを保証します。ただし、最適化のためにリリース モードでは、ポインタが初期化されておらず、ランダムなメモリ ブロックを解放しようとすると、上記のクラッシュが発生します。

于 2009-10-26T04:50:30.150 に答える