プログラミングスタイルとデザインを無視して、スタックに割り当てられた変数でdeleteを呼び出すのは「安全」ですか?
例えば:
int nAmount;
delete &nAmount;
または
class sample
{
public:
sample();
~sample() { delete &nAmount;}
int nAmount;
}
No 、スタックに割り当てられた変数でdelete
を呼び出すのは安全ではありません。 delete
によって作成されたものに対してのみnew
を呼び出す必要があります。
malloc
またはcalloc
ごとに、free
が1つだけ存在する必要があります。new
ごとに、正確に1つのdelete
が必要です。new[]
は1つだけですdelete[]
。一般に、これらのいずれかを組み合わせて使用することはできません。 free
- ingまたはdelete[]
-new
オブジェクトの入力。これを行うと、未定義の動作が発生します。
さて、試してみましょう:
jeremy@jeremy-desktop:~$ echo 'main() { int a; delete &a; }' > test.cpp
jeremy@jeremy-desktop:~$ g++ -o test test.cpp
jeremy@jeremy-desktop:~$ ./test
Segmentation fault
どうやら安全ではないようです。
New(またはmalloc)を使用してメモリブロックを割り当てると、割り当てられた実際のメモリブロックは、要求したものよりも大きくなることに注意してください。メモリブロックには簿記情報も含まれているため、ブロックを解放すると、簡単に空きプールに戻され、場合によっては隣接する空きブロックと合体できます。
あなたが新しいから受け取っていないメモリを解放しようとすると、その簿記情報はそこにはありませんが、システムはそのように動作し、結果は予測不能です(通常は悪い)。
はい、未定義の動作です:delete
から来なかったものをnew
に渡すと、UBになります。
C++標準、セクション3.7.3.2.3:標準ライブラリで提供される割り当て解除関数の1つに提供される最初の引数の値は、
null
ポインタ値です。その場合、および割り当て解除関数が標準ライブラリで提供されるものである場合、割り当て解除関数の呼び出しは効果がありません。それ以外の場合、標準ライブラリのoperator delete(void*)
に提供される値は、標準ライブラリのoperator new(std::size_t)
またはoperator new(std::size_t, const std::nothrow_t&)
の前回の呼び出しで返された値のいずれかです。
未定義の動作の結果は、未定義です。 「何も起こらない」ということは、他のことと同じくらい有効です。ただし、通常は「すぐには何も起こりません」:無効なメモリブロックの割り当てを解除すると、その後のアロケータの呼び出しで重大な結果が生じる可能性があります。
Windowsでg ++ 4.4を少しプレイした後、非常に興味深い結果が得られました。
スタック変数でdeleteを呼び出しても何も実行されないようです。エラーはスローされませんが、削除後に問題なく変数にアクセスできます。
delete this
を持つメソッドを持つクラスがあると、オブジェクトがヒープに割り当てられている場合は正常に削除されますが、スタックに割り当てられている場合は削除されません(スタックにある場合は何も起こりません)。
誰も何が起こるかわかりません。これは未定義の動作を呼び出すため、文字通り何でも起こります。 これをしないでください。
いいえ、newを使用して割り当てられたメモリはdelete演算子を使用して削除する必要があり、mallocを使用して割り当てられたメモリはfreeを使用して削除する必要があります。そして、スタックに割り当てられている変数の割り当てを解除する必要はありません。
天使は翼を失います... delete
で割り当てられたポインターでのみnew
を呼び出すことができます。そうでない場合、未定義の動作が発生します。
ここではメモリはスタックを使用して割り当てられるため、外部から削除する必要はありませんが、動的に割り当てられている場合
int * a = new int()のような
メモリは空きストアから割り当てられるため、aを削除する必要があり、aを削除する必要はありません(それ自体はポインターです)。
あなたはすでに自分で質問に答えました。 delete
は、new
を介して操作されるポインターにのみ使用する必要があります。それ以外のことは、単純で未定義の動作です。
したがって、実際に何が起こるかは言うまでもありません。正常に動作するコードからクラッシュしてハードドライブを消去するまでのすべてが、これを行うことの有効な結果です。 絶対にしないでください.
Newで動的に割り当てられていないアイテムでdeleteを呼び出してはならないため、これはUBです。とても簡単です。