4

別のC++ポインター削除の質問は、次の例にあります。

class Foo {
public:
    int *p;
    ~Foo() {
        delete p; p = NULL;
    }
};

Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p = new int(1);
f2->p = f1->p;
delete f2; // ok
delete f1; // no error?

「deletef1」を呼び出したときにエラーが発生しなかったのはなぜですか?同じアドレス(* p)を2回削除しませんでしたか?

コードの最後の2行のポインターを直接削除すると、エラーが発生します。

delete f2->p; // ok
delete f1->p; // error!! *** glibc detected *** double free or corruption (fasttop) ***
4

5 に答える 5

5

それは非常に悪いことです。ただし、C++は必ずしもここで何もしません。これは「未定義」の動作です。それはクラッシュするという意味ではありませんが、おそらく、悪いたわごと(tm)が発生する原因になります。

編集:さらに、2番目の例では、クラッシュするという事実は「未定義」の動作の一部にすぎません。反応がどうなるかは未定義です。

于 2010-10-15T09:34:24.277 に答える
3

私を信じてください、あなたはそれをしたくありません。

見てみましょう:ポインタの削除についてあまりboost::shared_ptr気にすることなく、エレガントな方法でポインタを処理することができます。

class Foo {
public:
    boost::shared_ptr<int> p;
};

Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p.reset(new int(1));
f2->p = f1->p;
delete f2; // ok
delete f1; // no error and its guaranteed !

を使用したくない場合は、同様のセマンティクスを持つboostコンパイラがすでに提供されています。std::tr1::shared_ptr

于 2010-10-15T09:38:16.360 に答える
3

「deletef1」を呼び出したときにエラーが発生しなかったのはなぜですか?同じアドレス(* p)を2回削除しませんでしたか?

はい、そのオブジェクトを2回削除しました。

ただし、その結果は未定義動作です。その結果、ランタイムシステムエラーをキャッチしてメッセージをポップアップする可能性がありますが、HDがフォーマットされ、厄介なNasal Demonsがオフィスの周りを追いかけて、同僚やあなたを喜ばせる可能性もあります。またはあなたのガールフレンドが妊娠します。または、この場合の意味が何であれ、「機能」しているように見えることもあります。

于 2010-10-15T10:51:54.470 に答える
1

同じメモリへの複数のポインタを使用する場合は、それらをにカプセル化しますboost::shared_ptr。これにより、基になるメモリへの最後の参照がスコープ外になるまで、基になるメモリが削除されないようになります。

#include <boost/shared_ptr.hpp>

class Foo {
public:
    boost::shared_ptr<int> p;
    ~Foo() {
      p.reset();
    }
};

Foo *f1 = new Foo();
Foo *f2 = new Foo();
f1->p.reset(new int(1));
f2->p = f1->p;
delete f2; // ok
delete f1; // no error
于 2010-10-15T09:38:36.683 に答える
0

もちろん、二重削除は未定義の動作です。デバッグビルドとリリースビルドの間でも変更される可能性があります。他の人はあなたにその良さなどを指摘していますboost::shared_ptr

ただし、これらの種類のバグを確実に見つける方法についても言及しておくと便利です。

valgrindでプログラムを実行します。

Windowsでは、purifyはvalgrindの古い商用版です。

于 2010-10-15T12:37:45.000 に答える