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