argv[0]の内容を出力するテストを作成します。これはメイン関数のパラメーターのアドレスです。
printf("%p\n",argv[0]);
Windows7のVisualStudio2008でプログラムをコンパイルしました。
次に、プログラムを1000回実行して、結果をファイルに出力しました。その結果、argv [0]のアドレスは変更されますが、一部のアドレスは同じであり、約10回繰り返されます。
メイン関数のパラメータのアドレスが毎回変わるのはなぜですか?
argv[0]の内容を出力するテストを作成します。これはメイン関数のパラメーターのアドレスです。
printf("%p\n",argv[0]);
Windows7のVisualStudio2008でプログラムをコンパイルしました。
次に、プログラムを1000回実行して、結果をファイルに出力しました。その結果、argv [0]のアドレスは変更されますが、一部のアドレスは同じであり、約10回繰り返されます。
メイン関数のパラメータのアドレスが毎回変わるのはなぜですか?
argc
argv
バイナリ実行可能ファイルのメインルーチンの開始前にスタックに配置する必要があります。実際にargv
は、ヒープ内のどこかに動的に割り当てられ、ポインターがスタックに配置されると思います。
これは、ヒープアロケーターがデータがどこに割り当てられるかを気にするものであることを意味し、これが毎回変更される理由です(ポリシーに依存します)..プログラムはOSに引数用のスペースを割り当てるように要求します(考えてみてくださいを通過するmalloc
)そのため、何か(彼らが話していた ASLR など)に従って行われる内部選択がある可能性があります。
興味深い質問です。プログラム自身のアドレス空間で非決定性が生じる理由はほとんど、またはまったくありません。しかし、私が知っていることをお話しします。
まず、argv はウィンドウではなく stdc ランタイムによって割り当てられ、作成され、初期化されます。これにより、別の疑問が生じます - winmain の lpCmdLine パラメータも変更されますか? 同じヒープに割り当てられた他の変数がいくつかあります。おそらく、環境変数もコピーされます。そのうちの 1 つは、実行のインスタンスに応じたサイズでなければなりません。
とにかく、なぜブラックボックスで熟考するのですか?あなたの逆アセンブラーはどこですか、兵士?
まず第一に、言語標準 ( n1256 ) の内容は次のとおりです。
5.1.2.2.1 プログラムの起動
...
2 宣言されている場合、main 関数へのパラメータは次の制約に従う必要があります。
- の値は
argc
非負でなければなりません。
argv[argc]
ヌルポインタでなければなりません。
- の値が
argc
0 より大きい場合、 inclusiveargv[0]
からargv[argc-1]
inclusive までの配列メンバーには、プログラムの起動前にホスト環境によって実装定義の値が与えられる文字列へのポインターが含まれます。その目的は、ホスト環境の他の場所からプログラムを開始する前に決定された情報をプログラムに提供することです。ホスト環境が大文字と小文字の両方の文字を含む文字列を提供できない場合、実装では、文字列が小文字で受信されるようにする必要があります。
- の値が
argc
0 より大きい場合、 が指す文字列はプログラム名argv[0]
を 表します。プログラム名がホスト環境から利用できない場合、ヌル文字になります。の値が1 より大きい場合、 ~ が指す文字列はプログラム パラメータを 表します。argv[0][0]
argc
argv[1]
argv[argc-1]
- 配列が指すパラメータ
argc
およびargv
文字列はargv
、プログラムによって変更可能であり、プログラムの起動からプログラムの終了までの間、最後に格納された値を保持します。
最後の箇条書きは、渡された文字列引数が格納される場所に関して最も興味深いものです。main
それらは変更可能である必要があり、静的な範囲を持っている必要があります。これにより、メモリ内の場所にいくつかの制限が課されます。ただし、プログラムが実行されるたびに同じ場所に存在するという言語定義の要件はありません。
MSDN を大雑把に検索して、明示的な発言があるかどうかを確認しましたが、まだ何も見つかりませんでした。OPへのコメントで述べたように、おそらくASLRに帰着します。