int main() {
Employee *e = new Employee();
delete e;
delete e;
...
delete e;
return 0;
}
8 に答える
ポインターを介してオブジェクトに複数回アクセスしようとすると、未定義の動作が発生します。delete
これは、「動作しているように見える」から「クラッシュ」または完全にランダムなものまで、ほとんどすべてが発生する可能性があることを意味します。
これは未定義の動作であるため、何が起こる可能性があります。
起こりそうなことは悪いことです。通常、フリーストアは、空きブロックと割り当て済みブロックの慎重に管理されたシステムであり、すべてを一貫した状態に保つために簿記を行いますnew
。delete
もう一度行うとdelete
、システムは無効なデータに対して同じ簿記を行う可能性が高く、突然フリー ストアが一貫性のない状態になります。これは「ヒープ破損」として知られています。
これが発生すると、アプリケーションのメモリ領域外に書き込もうとしたり、黙ってデータを破損したり、メモリがもうないと誤って考えたり、割り当てが二重または重複しnew
たりするなど、予測できない結果が生じる可能性があります。delete
運が良ければ、プログラムはすぐにクラッシュしますが、その理由を突き止めるにはまだ問題があります。運が悪いと、悪い結果で実行し続けます。
「未定義の動作」についての古い見たものは別として、何もない状態から、メイン メモリに開いているインフェルノの第 7 サークルへのゲートウェイまで、何でも起こり得ることを意味します。削除し、後で関係のないメモリ割り当てで不思議なことにクラッシュします。
「未定義の動作」の領域に足を踏み入れている可能性があります。
多くのシステムでは、これによりクラッシュが発生します。たとえば、私の Linux マシンでは次のようになります。
*** glibc detected *** ./cctest: double free or corruption (fasttop): 0x0000000000d59900 ***
======= Backtrace: =========
/lib/libc.so.6[0x7f399f4cbdd6]
/lib/libc.so.6(cfree+0x6c)[0x7f399f4d074c]
./cctest[0x400a7a]
/lib/libc.so.6(__libc_start_main+0xfd)[0x7f399f474abd]
./cctest[0x400959]
本当に運が良ければ壊れます。通常、CEO が最も重要な新規顧客にコードをデモンストレーションするまで、カルマが蓄積されます。コードがすべてのデータを破損/破壊するときです。
チェック ビルドまたはデバッグ ビルドでは、この種のことがよく検出されますが、完全に検出されず、後で大混乱を引き起こす可能性があります。これは、複数のスレッドが関与する場合に特に深刻です。
アプリでこれが発生する可能性があることを心配している場合は、未加工のポインターの使用を完全に停止して、削除する必要がないようにするか (たとえば、 に切り替える)、削除した後はshared_ptr
常にポインターをNULL
(または 0、またはさらに良いnullptr
) に設定します。null ポインターで delete を呼び出しても、何も行われないことが保証されています。
安全ではなく、実際に何が起こるかは未定義です。
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.2