なぜ私は「これを削除し、」後「は、この」値を使用しようとするべきではないのですか?
-
18-09-2019 - |
質問
でdelete this
構築物のC ++よくある質問の使い方のこの段落は、議論。 4つの制限が記載されています。
制限事項1〜3は、非常に合理的に見えます。しかし、なぜ私が「それを調べて、別のポインタと比較し、NULLと比較、それを印刷し、それを投げ、それを何もしてはならない」ということが制限4ているのですか?
私はthis
はまだ別のポインタであることを意味します。なぜ私は、その値をreinterpret_cast
にそれをint
または出力にprintf()
を呼び出すことはできません?
解決
あなたがそれ(この、または任意の他のポインタ)を削除した後、あなたがポインタで何もできない理由は、トラップがレジスタに無効なメモリアドレスをロードしようとしているハードウェアが(と一部の古いマシンではなかった)可能性があることです。それはすべての近代的なハードウェア上に微細であっても、標準では、あなたが(初期化されていないか、削除された)無効なポインタに行うことができる唯一のことは、(どちらかNULL、または別の有効なポインタから)それに割り当てることであると述べています。
他のヒント
を削除呼び出した後のthisの値は未定義であり、あなたがそれを行うものの動作は未定義です。私はほとんどのコンパイラは賢明な何かを期待するだろうが、この特定のケースでは、その動作は、ハード・ディスクをフォーマットするためのコードを放出されることを決定するから、コンパイラを停止する(仕様では)何もありません。未定義の動作を呼び出すと、あなたの特定のコンパイラは、あなたがそれをたいように動作した場合でも、常に(ほぼ)間違いあります。
あなたは削除を呼び出す前に(整数として)ポインタのコピーをとることによって、この問題を回避できます。
なるほど!
3.7.3.2/4:」...解放関数は、すべてのポインタが割り当て解除ストレージのどの部分を指す無効なレンダリング、ポインタが参照するストレージの割り当てを解除するものとし、それを渡すなど、無効なポインタ値を使用しての効果を(。 「定義されていない)メモリ解放関数へ。
「ポインタデリファレンス」ではない、これは「値を使用して」と言うことに注意してください。
その段落は、それが削除されているものに適用され、this
に固有ではありません。
あなたはそのポインタを取ることができます任意のアクションがクラッシュにつながる可能性があり、そのオブジェクトのクラスメソッドに解釈されるロジックを引き起こす可能性があるため。
さて、あなたはを指すアクションのいくつかは明らかに「安全」かもしれないが、それはあなたが呼び出すことができます任意のメソッド内で何が起こるかを言うのは難しいのです。
ポストから:?
「それで何かを、それを投げ、それを印刷し、NULLと比較し、他のポインタと比較し、それを検討してはなりません」すべてのこれらのアクションは未定義ポインタで評価されるオペレータに関連する機能をトリガすることができます。鋳造用同上ます。
あなたがreintepret_castを実行する場合は、は今、それはおそらく別の話だし、再解釈は(私の知る限り)任意のメソッド呼び出しを介さず、ビット再解釈によって少しだけあるとして、あなたはおそらく、それに沿って得ることができます。
同じ理由から、あなたは、他のポインタを削除しないだろうし、それ上の任意の操作を試してみて、実行します。
B /これは今まで、それは未定義参照し、あなたがそこにあるかもしれないのか分からないアドレスC ...
マルチスレッドのプログラムでは、あなたは、空き領域を指すポインタをdelete
瞬間はthis
が使用する領域を上書きし、別のスレッドによって割り当てることができます。でも、シングルスレッドプログラムでは、しない限り、あなたがreturn
ing前に呼んでいるものについては非常に慎重にね、何でもあなたがdelete this
で指されていたものメモリを割り当て、上書きする可能性がthis
後に行います。
のMicrosoft Visual C ++実行可能なデバッグモードでコンパイルでは、ポインタをdelete
ingはこのようなダングリングポインタのバグを識別するのに役立つように、(未初期化変数は、このパターンで初期化されている)、そのメモリは0xCCテストパターンとすぐに上書きさせます1。
これは私が火災の総数が一定数に達した場合は火災のオブジェクトのコンストラクタは、最古の火を削除するオンライン・プレイ可能なゲームのバグを修正したときのことを思い出します。削除された火災は時々新しい火を作成し、親の火災だった - BAM、ポインタのバグをダングリング!それ以外の場合は、オンラインのプレイヤー間の非同期化を引き起こしているだろう - それは、このバグは、(削除火は常に同じ方法で、新しい火災で上書きして)完全に予測可能な方法でメモリ割り当てアルゴリズムと相互作用することによってのみ幸運でした。ゲームはメモリ割り当てを行った方法を書き換えるとき、私はこのバグを見つけました。私はそれを修正する場合、その予測可能性に、私はまた、古いゲームクライアントとの互換性のために、その動作のエミュレーションを実装することができました。