2012-04-27 6 views
0

可能性の重複:
Can a local variable's memory be accessed outside its scope?なぜローカルメモリを指しているポインタを返すことが崩壊しないのですか?

私はFに次の呼び出しは()に従って、危険である(コンパイラによって処理されないローカルメモリへのポインタを取得すると思いました教科書へ)。しかし、それでもうまくいきます。これが安全かどうかは不明です。

#include <iostream> 

using namespace std; 

int * f() 
{ 
    int v[1000000]; 
    for (int i=0; i<1000000; i++) v[i]=i; 
    cout<<v[7]<<endl; 
    return v; 
} 

int main() 
{ 
    int * v = f(); 
    cout<<v[7]<<endl; 
    return 0; 
} 

答えて

4

興味深い質問です。あなたのコードは、一部のプラットフォームで動作する(または動作すると思われる)可能性があり、他のプラットフォームでは動作しない可能性があります。あなたのコードが動作しているよう

理由は、スタック上のメモリ機能f()埋蔵がをリリースしたがときf()戻っを消去されていないということです。解放されると、メモリは他の機能が利用できるようになります。他の関数が実際にそれを使用するまで上書きされない可能性があります。

ここでは、コードが定義されていない動作を引き起こしていることを正確に指摘しています。しかし、あなたが取得している特定の未定義の動作を取得する理由があります、それは私の答えについてです。

x86を含む一部のプラットフォームでは、f()v[]のメモリを解放した後、再利用される最初のメモリは通常v[999999]を保持するメモリになります。 v[0]を保持するメモリが再利用されるまでには長い時間がかかるかもしれません。したがって、v[7]のデータは偽ってまだ存在しています。

少なくとも1つ以上のシワがあります。いくつかの設定を使用する実装によっては、解放されたすべてのメモリがランダムなデータで直ちに上書きされ、セキュリティ上のリスクを防ぐことができます。 (たとえば、v[]がパスワードを保持していた場合はどうなりますか?ランダムなデータは安全に拭き取ります。)

4

ポインタmain()vf()復帰後にダングリングポインタです。ダングリングポインタを間接参照すると、何が起こることができることを意味し、未定義の動作です:

  • それはそれが正しい整数値に
4

を印刷することができ、誤った整数値

  • を印刷することができ
  • をクラッシュさせる可能性がありますそれは未定義の動作であり、未定義の動作は必ずしもクラッシュを意味しないためです。
    安全ではありません。
    未定義の行動とは、すべての安全な賭けが解除されていることを意味し、文字通り何らかの事態が起こる可能性があるため、墜落しても有効ではありません。それは無効で、あなたはそれをしないでください!

  • 1

    未定義の動作:ハードドライブを動作させたり、クラッシュしたり、ハードドライブを消去したり、ブラックホールに侵入したり、妻と逃げたりできます。

    確かに一つのことですが、それはあなたのクラスを失敗させるでしょう。

    +0

    おそらく、関数 'f'の名前を 'demo_undefined_behavior'に変更し、A? –

    1

    他の回答に記載されているように、定義されていない動作であるため、正しく動作することはできません。いくつかのプラットフォームやコンパイラではうまくいくかもしれませんが、他のコンパイラではうまくいきません。主にあなたのプログラムが小さくてシンプルであるために、あなたは「それを取り除いています」。プログラムを詳しく説明するほど、問題にぶつかる可能性が高くなります。

    関連する問題