2013-09-16 67 views
0

出於好奇,當使用MSVCR編譯的應用程序加載時會發生什麼, Windows的加載程序如何實際初始化CRT?對於我目前收集的內容,當程序以及所有導入的庫被加載到內存中並且所有的重定位完成時,CRT啓動代碼(_CRT_INIT()?)初始化.CRT$XC*部分中的所有全局初始化程序,並調用用戶定義的main()功能。我希望迄今爲止這是正確的。我們假設,爲了解釋起見,不使用MSVCR的程序(例如,用Cygwin GCC或其他編譯器構建的應用程序)試圖在運行時加載庫,需要CRT,使用自定義加載器/運行時鏈接程序,因此不涉及LoadLibrary()。加載器/鏈接器如何處理CRT初始化?是否必須手動初始化所​​述部分中的所有「對象」,是否必須執行其他操作才能使庫的內部接線正常工作,還是必須調用_CRT_INIT()(在運行時本身中定義的不切實際,據我所知,沒有出口到任何地方)。假設非CRT應用程序和CRT庫不會傳遞任何對象,例外和它們之間的事情之類,這種混淆甚至會以任何方式工作嗎?MSVCR和CRT初始化

我會找到出去很感興趣,因爲我不能完全讓出了什麼CRT對實際加載過程的影響...

的所有信息都非常感謝,謝謝!

回答

2

針對C++運行庫編譯的每個庫在加載時調用_DllMainCRTStartup。 _DllMainCRTStartup調用_CRT_INIT,它初始化C/C++運行時庫並在靜態非本地變量上調用C++構造函數。

PE格式包含一個可選標頭,其中有一個名爲'addressofentrypoint'的插槽,該插槽調用一個函數,該函數將調用_DllMainCRTStartup來觸發初始化鏈。

_DllMainCRTStartup完成初始化階段後,它會調用你自己實現的DllMain()函數。

+0

好吧 - 所以基本上所有的CRT初始化都是「只是」_DllMainCRTStartup()在crtdll.c源文件中執行的所有操作倖運的是與VS發貨,所以每個人都可以看看它:-))?我必須說,這比我最初想象的要少得多「魔術」,但另一方面......我還期望別的什麼? ;)謝謝你的澄清! – PuerNoctis

+0

那裏沒有魔法,我很抱歉地解僱你。 –

2

當你瞭解編程知識時,有人會告訴你「發生的第一件事是代碼在main中運行,但是當你在學校學習原子時,它們有點像它們組織得很好並且操作起來很順利如果你後來去上大學的核/粒子物理課,那些簡單/嚴格的規則就更加詳細,並不總是適用,等等。

當你連接一個C或C++程序時,CRT包含如下代碼:

start() 
{ 
    CRT_init(); 
    ... 
    Global_Object_Constructors(); 
    ... 
    exit(main()); 
} 

所以初始化是由C運行時庫本身,它調用你的主。

DLL有一個DllMain,由LoadLibrary()執行 - 它負責初始化/創建DLL中的全局對象,並且如果你不使用LoadLibrary() [例如,將DLL自動加載到內存中],那麼你將不得不確保對象被創建和初始化。

3

使用/ ENTRY鏈接器選項選擇可執行映像的入口點。它使用的默認值在MSDN Library article中有很好的記錄。他們是CRT的入口點。

如果您想要替換CRT,請選擇相同的名稱或在鏈接時明確使用/ ENTRY選項。你還需要/ NODEFAULTLIB來阻止它鏈接正常的.lib