0

重複の可能性:
ローカル変数のメモリにそのスコープ外でアクセスできますか?

次の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

5 に答える 5

4

のポインタvは、戻りmain()後のダングリングポインタです。f()ダングリングポインタの間接参照は未定義の動作です。つまり、何かが発生する可能性があります。

  • クラッシュする可能性があります
  • 誤った整数値を出力する可能性があります
  • 正しい整数値を出力できます
于 2012-04-27T15:31:53.310 に答える
4

これは未定義動作であり、未定義動作は必ずしもクラッシュを意味するわけではないためです。
もちろん安全ではありません。
未定義動作とは、すべての安全な賭けが無効になり、文字通り何かが発生する可能性があることを意味します。したがって、クラッシュしない場合でも、それが有効であるとは限りません。それは無効であり、あなたはそれをすべきではありません!

于 2012-04-27T15:31:53.653 に答える
4

興味深い質問です。コードは、一部のプラットフォームでは機能する(または機能するように見える)可能性があり、他のプラットフォームでは失敗する可能性があります。

コードが機能しているように見える理由は、関数f()がスタックに予約しているメモリは解放されますが、戻ったときに消去されないためです。f()解放されると、メモリは他の機能で使用できるようになります。ただし、別の関数が実際に使用するまで上書きされない場合があります。

ここにいる他の何人かは、あなたのコードが未定義の振る舞いを呼び起こすことを正しく指摘しています、そして技術的にはそれは本当です。ただし、特定の未定義の動作が発生するのには理由があり、それが私の答えです。

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

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

于 2012-04-27T15:35:27.947 に答える
1

未定義の動作:動作したり、クラッシュしたり、ハードドライブを消去したり、ブラックホールに内破したり、妻と一緒に逃げたりする可能性があります。

ただし、確かなことが1つあります。それは、クラスに失敗する原因になります。

于 2012-04-27T15:34:21.220 に答える
1

他の回答で述べられているように、これは未定義の動作であるため、正しく機能しているとは言えません。一部のプラットフォームまたは一部のコンパイラでは正常に動作する可能性がありますが、他のコンパイラでは動作しない場合があります。あなたは主にあなたのプログラムが小さくて単純だからです。プログラムを詳しく説明すればするほど、問題が発生する可能性が高くなります。

于 2012-04-27T15:40:34.310 に答える