2016-05-05 6 views
1

いくつかのプログラムを実行すると、仮想アドレスは常に4の倍数(32ビットの仮想アドレスを仮定)であることに気付きました。例: 仮想アドレス:複数の4つのアライメント "〜の間のアドレス"への書き込み

  • xfff58f80 0xfff58f84
    • xff86c930 0xff86c934
    • ...

    その差は常に4です:

    int main() 
    { 
        int a = 7; 
        int b = 10; 
        printf("%p %p", &a, &b); 
    } 
    

    のようなものを与えるだろう。 は今、私はこれを試してみました:

    int main() 
    { 
        int a = 7; 
        int b = 10; 
        int *y = &b; 
        int yi = (int)y; 
        yi--; 
        y = (int*)yi; 
        printf("%p %p: %d\n", &b, y, *y); 
        *y = 7; 
        printf("%p: %d\n", y, *y); 
    } 
    

    一例の出力は次のとおりです。

    0xffe460a0 0xffe4609f:2807

    0xffe4609f:7

    ここで何が起こっていますか? 4の倍数ではないアドレスに何かを書き込もうとするときに参照されるものは何ですか?この2807はどこから来たのですか?ページフォールトはありますか?

  • +2

    '仮想アドレスは常に4の倍数です.'それは真ではありません –

    +0

    これは未定義の動作と呼ばれます。無効なポインタになるように 'y'を操作しました。 – kaylum

    +0

    @Lashaneはこのアーキテクチャを前提としています...これを私の質問に追加します。 –

    答えて

    1

    int yi = (int)y; 
    

    デクリメント整数ではなくポインタとしてそのアドレス(64ビットシステム上の危険)intとしてYを取る - それは非整列になる場合があります。そのバックポインタとして、新たな整数

    yi--; 
    

    ハードコード - このポインタは今整列していないポインタデリファレンス

    y = (int*)yi; 
    

    を使用して、おそらく非常に危険です。これは、メモリコントローラによって異なるシステム上で異なる処理を行います。せいぜい、それは直ちに断層を形成するので、あなたは何の前提もなしません。

    printf("%p %p: %d\n", &b, y, *y); 
    

    お楽しみのためにアライメントされていないメモリをいくつかお試しください。

    *y = 7; 
    

    どこから来たのですか?メモリコントローラがあなたに与えたいことは何でもあります。おそらく、それはスタックの早い段階でのゴミ値であり、おそらくそれは下の単語のバレルシフトされた値です。これは完全にシステムの選択です。

    これは、@ kaylumがUBのコメントで意味したものです。

    +0

    ありがとうございます。 –

    +0

    @Michael、32ビット(32ビットプロセッサ)でメモリを整列させる必要があるのはなぜですか?この制限があります....私の疑問はプロセッサが一度に32ビットを読み込まないことです。なぜ、32ビットアラインメントが必要なのですか?それはキャッシュラインアラインメントに依存するはずです。 –

    関連する問題