IP_ADAPTER_INFO *ptr=new IP_ADAPTER_INFO[100];
自由に使ったら
delete ptr;
そうでない場合、それはメモリリークにつながるのでしょうか?
これはVS2005によって生成された逆アセンブリコードです
; delete ptr;
0041351D mov eax,dword ptr [ptr]
00413520 mov dword ptr [ebp-0ECh],eax
00413526 mov ecx,dword ptr [ebp-0ECh]
0041352C Push ecx
0041352D call operator delete (4111DBh)
00413532 add esp,4
; delete []ptr;
00413535 mov eax,dword ptr [ptr]
00413538 mov dword ptr [ebp-0E0h],eax
0041353E mov ecx,dword ptr [ebp-0E0h]
00413544 Push ecx
00413545 call operator delete[] (4111E5h)
0041354A add esp,4
これがメモリリークにつながるか、ハードディスクをワイプするか、妊娠するか、厄介な鼻の悪魔があなたのアパートの周りを追いかけるか、または明らかな問題なしにすべてが正常に機能するかどうかは未定義です。これは、あるコンパイラではこのようになり、別のコンパイラで変更され、新しいコンパイラバージョンで変更され、新しいコンパイルごとに、月の満ち欠け、気分、または最後の晴れた日にプロセッサを通過したニュートリノの数によって異なります。午後。またはそうではないかもしれません。
そのすべて、そして他の無限の可能性が1つの用語にまとめられています:未定義の振る舞い:
近づかないでください。
特定のOSおよびコンパイラでのいくつかの「未定義」の動作の単なる図解。人々が自分のコードをデバッグするのに役立つことを願っています。
テスト1
#include <iostream>
using namespace std;
int main()
{
int *p = new int[5];
cout << "pass" << endl;
delete p;
return 0;
}
テスト2
#include <iostream>
using namespace std;
int main()
{
int *p = new int;
cout << "pass" << endl;
delete[] p;
return 0;
}
テスト3
#include <iostream>
using namespace std;
struct C {
C() { cout << "construct" << endl; }
~C() { cout << "destroy" << endl; }
};
int main()
{
C *p = new C[5];
cout << "pass" << endl;
delete p;
return 0;
}
テスト4
#include <iostream>
using namespace std;
struct C {
C() { cout << "construct" << endl; }
~C() { cout << "destroy" << endl; }
};
int main()
{
C *p = new C;
cout << "pass" << endl;
delete[] p;
return 0;
}
テスト1
pass
テスト2
pass
テスト3
construct
construct
construct
construct
construct
pass
destroy
# Then, pop up crash msg
テスト4
construct
pass
destroy
destroy
destroy
destroy
destroy
destroy
destroy
... # It never stop until CTRL+C
テスト1
pass
テスト2
pass
テスト3
construct
construct
construct
construct
construct
pass
destroy
a.out(71111) malloc: *** error for object 0x7f99c94000e8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
zsh: abort ./a.out
テスト4
construct
pass
a.out(71035) malloc: *** error for object 0x7f83c14000d8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
zsh: abort ./a.out
テスト1
pass
テスト2
pass
テスト3
construct
construct
construct
construct
construct
*** glibc detected *** ./a.out: munmap_chunk(): invalid pointer: 0x0000000001f10018 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fe81d878b96]
./a.out[0x400a5b]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fe81d81b76d]
./a.out[0x4008d9]
======= Memory map: ========
....
zsh: abort (core dumped) ./a.out
テスト4
construct
destroy
destroy
destroy
destroy
destroy
destroy
destroy
destroy
...
destroy
destroy
*** glibc detected *** ./a.out: free(): invalid pointer: 0x00000000016f6008 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7fa9001fab96]
./a.out[0x400a18]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fa90019d76d]
./a.out[0x4008d9]
======= Memory map: ========
...
zsh: abort (core dumped) ./a.out
PODデストラクタの場合は些細なことであり、それらを呼び出す必要がないため、通常はリークしません。そのため、delete
は配列が占有するメモリの割り当てを解除するだけです。メモリの割り当て解除にはポインタ値のみが必要なので、ヒープに返されます。配列は連続したメモリブロックに対応しているため、単一の要素の割り当て解除であるかのように、割り当て解除を成功させることができます。
ただし、これは未定義の動作であるため、これに依存しないでください。多分それは大丈夫です、多分何か恐ろしいことが起こります、このコンパイラで動作します、別のものでは動作しません、そして多くの人々はエラーを植えてくれてありがとう。
詳細については、 この回答 を参照してください。
削除:適切な要素のデストラクタのみポイント(必要な場合)を呼び出し、メモリチャンクを解放します
delete []:配列内の適切な各要素のデストラクタを呼び出し(必要な場合)、メモリチャンクを解放します
新しいT [n]を使用した割り当てでの削除演算子の使用はndefinedであり、コンパイラーごとに異なります。 AFAIK、たとえばMSVCコンパイラはGCCとは異なるコードを生成します。
Aが新しいT [n]を介して割り当てられた配列を指している場合は、delete [] Aを介して削除する必要があります。deleteとdelete []の違いは簡単です。前者はスカラーオブジェクトを破棄し、後者は配列を破棄します。 。