5

以下に記述されているコードをWindowsとLinuxで実行すると、2つの出力が異なります。

私は両方にgccを使用しています。Windowsで実行すると、出力として「Seek」が表示されますが、Linuxで実行すると、出力として「Hide」が表示されます。WindowsとLinuxのメモリレイアウトに違いはありますか、それとも出力が異なる原因となるものはありますか?

int main()
{
    int a=0;
    int *b=(int *)malloc(sizeof(int));
    if(&a>b)
        printf("Hide");
    else
        printf("Seek");
    return 0;
}
4

3 に答える 3

9

はい、Windows と Linux ではメモリのレイアウトが異なります。いくつかの例をここに示します。たとえば、Windows は通常、メモリをカーネルとユーザー空間の間で (32 ビットで) 均等に分割しますが、Linux は 3/1 ユーザー/カーネルです。

コンパイラは、仕様の制限内で、適切と思われるメモリをレイアウトすることもできます。これは、llvm コンパイラ、gcc、およびこれらの異なるバージョンが異なる出力を持つ可能性があることを意味します。

最適化により、レイアウトが変更されたり、厳密には必要ない変数が削除されたりすることもあります。

また、メモリが低から高に割り当てられた場合でも、他のメモリが解放された後、以前に使用されていた領域から新しい割り当てが行われ、再び低になる可能性がありました。

簡単な答え: 無関係な変数間のメモリ レイアウト/場所を期待することはお勧めできません。

于 2012-07-27T12:20:05.943 に答える
0

Linuxでは、アドレス空間配置のランダム化が頻繁に発生します(これはWindowsでも発生する可能性があります)。したがって、比較すると、実行ごとに異なる結果が得られる可能性があります(特に、コードがランダムにmmap-edされる共有ライブラリ内にある場合)。

/proc/self/mapsまた、メモリマップを理解するために、次のLinux固有のコードを追加して表示できます。

{
   char linbuf[128];
   FILE* mapfil=("/proc/self/maps");
   if (!mapfil) 
     perror("/proc/self/maps"), exit(1);
   while (!feof (mapfil)) {
     memset(linbuf, sizeof(linbuf), 0);
     fgets(linbuf, sizeof(linbuf), mapfil);
     fputs(linbuf, stdout);
   };
   fclose(mapfil), fflush(NULL);
}

(そのコードをの後に置き、それなしですべてのフォーマット文字列にmallocを追加します)。\nprintf

pmapプログラムのプロセスIDがある場合は、ユーティリティを使用することもできます。

于 2012-07-27T14:12:12.023 に答える
0

の戻り値mallocは指定されていません (何でもかまいません)。つまり、標準のどの部分も、戻り値の予測可能性を保証していません。これは、プラットフォーム固有ではなく、C 言語標準の一部であり、実際にはメモリ レイアウトとは関係ありません。C99 標準から:

7.20.3 メモリ管理機能

1 calloc、malloc、および realloc 関数の連続呼び出しによって割り当てられるストレージの順序と連続性は指定されていません. 割り当てが成功した場合に返されるポインターは、任意の型のオブジェクトへのポインターに割り当てられ、割り当てられた空間内のそのようなオブジェクトまたはそのようなオブジェクトの配列にアクセスするために使用されるように適切に整列されます (空間が明示的に割り当て解除されるまで)。 . 割り当てられたオブジェクトの有効期間は、割り当てから解放まで延長されます。そのような各割り当ては、他のオブジェクトから切り離されたオブジェクトへのポインタを生成します。返されるポインタは、割り当てられた空間の開始 (最下位バイト アドレス) を指します。スペースを割り当てることができない場合は、ヌル ポインターが返されます。要求されたスペースのサイズがゼロの場合、動作は実装定義です: null ポインターが返されるか、サイズがゼロ以外の値であるかのように動作します。

あなたが遭遇したのは、将来的に保持されることが保証されていない実装定義の動作です。実際、現在のバージョンの Windows/Linux で保持されることさえ保証されていません。

于 2012-07-27T12:14:05.493 に答える