OSが関数を呼び出すよりも技術的な説明を探しています。
誰か助けてくれたり、ウェブサイトや本を教えてくれませんか?
.exe ファイル (または他のプラットフォームの同等ファイル) には、「エントリ ポイント」アドレスが含まれています。まず、OS は .EXE ファイルの関連セクションを RAM にロードし、エントリ ポイントにジャンプします。
他の人が言ったように、このエントリ ポイントは「メイン」ではなく、代わりにランタイム ライブラリの一部になります。静的オブジェクトの初期化、argc/argv パラメータの設定、stdin/stdout/stderr の設定などを行います。など。すべて完了すると、main() 関数が呼び出されます。main が終了すると、ランタイムはリターン コードを環境に戻し、静的デストラクタを呼び出し、_atexit ルーチンを呼び出すなどの類似のプロセスを実行します。
MS ツール (おそらく景品ではないもの) を持っている場合、すべてのランタイム ソースがあり、それを確認する簡単な方法は、main() メソッドの右中括弧にブレークポイントを置き、1 ステップ バックアップすることです。ランタイムに。
main()
C ライブラリの一部であり、システム関数ではありません。OS X や Linux についてはわかりませんが、Windows では通常、WinMainCRTStartup()
. このシンボルは、プロセスを開始し、コマンド ライン引数と環境 ( argc, argv, end
) を抽出し、 を呼び出しますmain()
。main()
また、 のように の後に実行する必要があるコードを呼び出す役割も担いますatexit()
。
Visual Studio ファイルを調べると、 のデフォルトの実装を見つけて、その機能を確認できるはずですWinMainCRTStartup
。
起動時に呼び出す独自の関数を定義することもできます。これは、リンカー オプションの「エントリ ポイント」を変更することによって行われます。これは多くの場合、引数を取らず、void を返す関数です。
Windows に関する限り、エントリ ポイント関数は次のとおりです。
void __cdecl mainCRTStartup( void ) {}
void __stdcall WinMainCRTStartup( void ) {}
BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}
通常の main/WinMain/DllMain でこれらを使用する唯一の理由は、独自のランタイム ライブラリを使用する場合です (より小さいファイル サイズまたはカスタム機能が必要な場合)。
カスタム ランタイムの実装と、より小さな PE ファイルを取得するためのその他のトリックについては、次を参照してください。
Expert C++/CLI (279 ページあたりを確認) には、ネイティブ、混合、および純粋な CLR アセンブリのさまざまなブートストラップ シナリオの非常に具体的な詳細が記載されています。
OS依存です。OS X では、EIP (命令ポインター) レジスターの開始アドレスを含むフレームが mach ヘッダーにあります。
バイナリがロードされると、OS は次のアドレスから実行を開始します。
cristi:test diciu$ otool -l ./a.out | grep -A 10 LC_UNIXTHREAD cmd LC_UNIXTHREAD cmdsize 80 フレーバー i386_THREAD_STATE カウント i386_THREAD_STATE_COUNT [..] ss 0x00000000 eflags 0x00000000 eip 0x00001f8c cs 0x00000000 [..]
アドレスは、バイナリからの「開始」関数のアドレスです。
cristi:test diciu$ nm ./a.out 0000200c D_NXArgc 00002008D_NXArgv 00002000 D ___プログラム名 00001fe0 t __dyld_func_lookup 00001000 __mh_execute_header [..] 00001f8c T スタート
Mac OS X では、「main」関数の前であっても、最初に呼び出されるのは「start」関数です。
(gdb) b スタート 0x1f90 のブレークポイント 1 (gdb) b メイン 0x1ff4 のブレークポイント 2 (gdb) r プログラムの開始: /Users/diciu/Programming/test/a.out 共有ライブラリ ++ のシンボルの読み取り。終わり ブレークポイント 1、開始 () の 0x00001f90