Szukam bardziej technicznego wyjaśnienia niż OS wywołuje funkcję. Czy ktoś może mi pomóc lub wskazać mi stronę lub książkę?W programie C/C++, w jaki sposób system (Windows, Linux, Mac OS X) wywołuje funkcję main()
Odpowiedz
plik .exe (lub równowartość w innych platformach) zawiera „punkt wejścia ' adres. Do pierwszego przybliżenia system operacyjny ładuje odpowiednie partycje pliku .EXE do pamięci RAM, a następnie przeskakuje do punktu wejścia.
Jak już powiedzieli inni, ten punkt wejścia nie będzie "głównym", ale zamiast tego będzie częścią biblioteki uruchomieniowej - będzie robił takie rzeczy jak inicjowanie obiektów statycznych, ustawianie parametrów argc/argv, konfigurowanie stdin/stdout/stderr, itd. Kiedy to wszystko zrobi, wywoła funkcję your main(). Podczas głównych wyjść środowisko wykonawcze przechodzi przez proces przetwarzania kodu zwrotnego z powrotem do środowiska, wywoływanie statycznych destruktorów, wywoływanie procedur _atexit itp.
Jeśli masz narzędzia MS (być może nie te z freebie), to mieć całe środowisko uruchomieniowe, a łatwym sposobem na sprawdzenie tego jest umieszczenie punktu przerwania w nawiasie klamrowym metody main() i pojedynczy krok z powrotem w środowisku wykonawczym.
main()
jest częścią biblioteki C i nie jest funkcją systemową. Nie wiem o OS X ani Linuxie, ale Windows zwykle uruchamia program z WinMainCRTStartup()
. Ten symbol rozpoczyna proces, usuwa argumenty wiersza poleceń i środowisko (argc, argv, end
) i wywołuje main()
. Jest również odpowiedzialny za wywoływanie dowolnego kodu, który powinien działać po main()
, jak atexit()
.
Patrząc w pliku Visual Studio, powinieneś być w stanie znaleźć domyślną implementację WinMainCRTStartup
, aby zobaczyć, co robi.
Można również zdefiniować własną funkcję wywołania przy uruchomieniu, odbywa się to poprzez zmianę "punktu wejścia" w opcjach linkera. Często jest to funkcja, która nie przyjmuje argumentów i zwraca pustkę.
Można również zapoznać się z następującymi linkami:
Expert C++/CLI (sprawdź na stronie 279) zawiera szczegółowe informacje na temat różnych scenariuszy ładowania początkowego dla natywnych, mieszanych i czystych zespołów CLR.
Jest zależny od systemu operacyjnego. W OS X, w nagłówku machu znajduje się ramka zawierająca adres początkowy rejestru EIP (wskaźnik instrukcji).
Po binarny jest załadowany, system operacyjny uruchamia wykonanie z tego adresu:
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 [..]
adres jest adresem funkcji "start" z binarnym:
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
W systemie Mac OS X, jest to funkcja "startowa", która jest wywoływana jako pierwsza, nawet przed "główną" funkcją:
(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()
O ile w indows idzie, funkcje punktu wejścia są:
- konsoli:
void __cdecl mainCRTStartup(void) {}
- GUI:
void __stdcall WinMainCRTStartup(void) {}
- DLL:
BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}
Jedynym powodem, aby z nich korzystać na normalną main/WinMain/DllMain jest jeśli chcesz użyć własnej biblioteki czasu wykonywania (jeśli chcesz zmniejszyć rozmiar pliku lub niestandardowe funkcje)
Dla niestandardowego czasu wykonywania implementat jony i inne sztuczki, aby uzyskać mniejsze pliki PE, patrz:
Jeżeli są Państwo zainteresowani w książce związanej z Windows i Win32 API spróbuj
"Programowanie aplikacji dla Mi crosoft Windows "autorstwa Jeffreya Richtera.
Kto głosował na zakończenie? To pytanie wydaje mi się całkowicie ważne. To jest dobre pytanie !!! – Destructor