2

私はポインターを使っていくつかのテストを行ってきましたが、次の2つのシナリオに出くわしました。誰かが私に何が起こっているのか説明できますか?

void t ();
void wrong_t ();

void t () {
        int i;
        for (i=0;i<1;i++) {
                int *p;
                int a = 54;
                p = &a;
                printf("%d\n", *p);
        }
}

void wrong_t() {
        int i;
        for (i=0;i<1;i++) {
                int *p;
                *p = 54;
                printf("%d\n", *p);
        }
}

mainの次の2つのバージョンを検討してください。

int main () {
        t();
        wrong_t();
}

プリント:54 \ n54 \ n、予想通り

int main () {
        wrong_t();
}

歩留まり:セグメンテーション違反:11

この問題は、「wrong_t()」の「int * p」が正しく初期化されていないため「不正なポインタ」であるという事実から生じていると思います(参照:cslibrary.stanford.edu/102/PointersAndMemory.pdf、8ページ) )。しかし、なぜこのような問題が発生するのかがわかりません(たとえば、wrong_t()の前にt()を呼び出した場合、またはwrong_t()のコードのforループを削除した場合は発生しません)。

4

3 に答える 3

4

初期化されていないポインターを逆参照すると (ご想像のとおり)、undefined behaviorが呼び出されるためです。なんでも起こる可能性がある。

観察している正確な動作を理解したい場合、唯一の方法は、コンパイラが生成したアセンブラ コードを調べることです。しかし、これは通常あまり生産的ではありません。

于 2013-02-18T23:56:03.917 に答える
3

ほぼ確実に次のことが起こります。

と の両方twrong_t、定義はスタックにint *pスペースを割り当てます。ponly を呼び出すと、このスペースには以前のアクティビティ (たとえば、が呼び出されるwrong_t前に環境をセットアップするコード) から残ったデータが含まれます。mainたまたまポインターとして有効でない値であるため、それを使用してメモリにアクセスすると、セグメント違反が発生します。

を呼び出すとt、は、 へのポインタを含むようにtこのスペースを初期化します。この後にを呼び出すと、 の空間の初期化に失敗しますが、実行時に fromへのポインターが既に含まれているため、それを使用してメモリにアクセスすると、 にアクセスすることになります。pawrong_twrong_tpata

これは明らかに、信頼できる動作ではありません。最適化を有効にして ( -O3GCC などで) コンパイルすると、動作が変わることがあります。

于 2013-02-19T00:02:44.313 に答える
1

関数ではwrong_t、このステートメント*p = 54;は興味深いものです。pまだメモリを割り当てていないポインタに値を格納しようとしているため、エラーが発生します。

于 2013-02-18T23:57:47.623 に答える