-1

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

次の単純な C++ コードを検討してください。

#include <iostream>

struct Test
{
    Test( int i )
        :   ref( i ),
            ptr( &i ) {}

    int &ref;
    int *ptr;
};

int main()
{
    Test t( 5 );

    std::cout << t.ref << std::endl;
    std::cout << *t.ptr << std::endl;

    return 0;
}

クラス Test は、スタック上に存在するローカル変数 i へのポインターと参照を格納します。テストコンストラクターから戻った後、私は破壊されたと思います。しかし、明らかにそうではありません。これはプログラムの出力であるため:

5
134513968

ポインターへのアクセスの結果は、私が期待するものです。つまり、実行ごとに変化するランダムな値です。ただし、ローカル変数 i がまだ存在する場合のみ、参照アクセスは常に 5 になります。

誰かが私にこの動作を説明できますか? 64 ビット Linux (バージョン 4.6.3) で g++ を使用しています。

よろしく、 enuhtac

4

5 に答える 5

6

そのように破棄された変数にアクセスすると、未定義の動作が発生します。5 と表示されたのは単なる偶然です。-4390843 または を印刷したりhello world、コンピューターをクラッシュさせたり、大気に火をつけたり、クレジット カードでピザを購入したりした可能性があります。

また、コンパイラはアセンブリを生成するときにコードに対して非常に奇妙なことを行う可能性があるため、何が起こったのかを推測しようとしても意味がありません。これは無益な演習です (ただし、すべてのビットがどこから来て、どこにあったのかを本当に知りたい場合は、デバッグしてください)。

于 2012-05-04T20:32:24.610 に答える
1

構築時に、構築中に格納されtているメモリアドレスを取得しますi。呼び出したときstd::cout << t.ref、そのメモリ ロケーションが別の目的で使用される理由がないため、値はまだそこにあります。

しかし、それはあなたが信頼できるものではありません。iスコープ外になった後にそのメモリ位置にアクセスするのは、未定義の動作です。

于 2012-05-04T20:33:41.303 に答える
0

詳しくは調べていませんが、スタックからポップしたからといって、内容が上書きまたは変更されたわけではなく、そのアドレスの値は変更されていません。後でメソッド呼び出しを追加すると、変更されるはずです。

于 2012-05-04T20:32:40.350 に答える
0

ローカル変数がすぐに削除されるとは限りません。記憶に残ることがあります。しかし、それは未定義の動作であり、危険です。

于 2012-05-04T20:33:38.883 に答える
0

この回答は、これについてどのように考えることができるかについての素晴らしいアナロジーを提供します:

あなたはホテルの部屋を借ります。ベッドサイドテーブルの一番上の引き出しに本を入れて寝ます。翌朝チェックアウトしますが、鍵を返すのを「忘れて」しまいます。あなたは鍵を盗む!

1 週間後、あなたはホテルに戻り、チェックインせず、盗んだ鍵で元の部屋に忍び込み、引き出しをのぞきました。あなたの本はまだそこにあります。驚くべき!

それはどうしてですか?部屋を借りていない場合、ホテルの部屋の引き出しの中身にアクセスできませんか?

于 2012-05-04T20:37:40.540 に答える