呼び出しで削除の変数を割り当てのスタック
-
22-07-2019 - |
質問
を無視してグスタイルデザインで"安全"と呼削除、変数の割り当てのスタック?
例えば:
int nAmount;
delete &nAmount;
または
class sample
{
public:
sample();
~sample() { delete &nAmount;}
int nAmount;
}
解決
No, ではない呼び出しても安全です delete
るスタックに割り当て可変となります。きのみお電話で delete
もの作成 new
.
- 各
malloc
またはcalloc
, があってしかるべきだと思うちょうど一free
. - 各
new
がちょうど一delete
. - 各
new[]
がちょうど一delete[]
. - 各スタックの配分がないと認められること明示的に解放や削除に応じます。のデストラクタは自動的に呼び出されることができます。
原則として応募できません、これらの例no 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を使用して削除する必要があります。 スタックに割り当てられている変数の割り当てを解除する必要はありません。
天使は翼を失います... new
で割り当てられたポインターでのみ delete
を呼び出すことができます。そうしないと、未定義の動作が発生します。
ここでは、スタックを使用してメモリが割り当てられるため、外部から削除する必要はありませんが、動的に割り当てられている場合は
like int * a = new int()
メモリをフリーストアから割り当てるため、& a(それ自体はポインタです)を削除せずに、aを削除する必要があります。
すでに自分で質問に答えました。 delete
は、 new
を介して操作されるポインターにのみ使用する必要があります。それ以外のことは、単純で未定義の単純な動作です。
したがって、実際に何が起こるのかは言うまでもありません。コードが正常に動作してからクラッシュしてハードドライブが消去されるまで、これは有効な結果です。そのため、これを行わないでください。
newで動的に割り当てられていないアイテムでdeleteを呼び出してはならないため、これはUBです。とても簡単です。