出于好奇,加载了使用MSVCR编译的应用程序时会发生什么。 Windows的加载程序如何实际初始化CRT?对于我到目前为止收集的内容,当程序以及所有导入的库加载到内存中并完成所有重定位时,CRT启动代码(_CRT_INIT()
?)初始化{{1}中的所有全局初始值设定项} section并调用用户定义的.CRT$XC*
函数。我希望到目前为止这是正确的。
但我们假设,为了便于解释,不使用MSVCR的程序(例如,使用Cygwin GCC或其他编译器构建的应用程序)尝试在运行时加载库,需要CRT,使用自定义加载器/运行时链接程序,因此不涉及main()
。加载器/链接器如何处理CRT初始化?它是否必须手动初始化所述部分中的所有“对象”,是否必须执行其他操作才能使库的内部布线正常工作,或者是否必须只调用LoadLibrary()
(不明确地定义在运行时本身,据我所知,不会导出到任何地方)。假设非CRT应用程序和CRT库不会传递它们之间的任何对象,异常和类似内容,这种混合是否会以任何方式工作?
我很想知道,因为我无法弄清楚CRT对实际装载过程有什么影响......
非常感谢任何信息,谢谢!
答案 0 :(得分:3)
使用/ ENTRY链接器选项选择可执行映像的入口点。它使用的默认值在MSDN Library article中很好地记录。它们是CRT入口点。
如果要替换CRT,请选择相同的名称,或在链接时显式使用/ ENTRY选项。您还需要/ NODEFAULTLIB来阻止它链接常规.lib
答案 1 :(得分:2)
针对C ++运行时编译的每个库在加载时都调用_DllMainCRTStartup。 _DllMainCRTStartup调用_CRT_INIT,它初始化C / C ++运行时库并在静态非局部变量上调用C ++构造函数。
PE格式包含一个可选标头,该标头有一个名为“addressofentrypoint”的插槽,此插槽调用一个函数,该函数将调用_DllMainCRTStartup来触发初始化链。
在_DllMainCRTStartup完成初始化阶段后,它将调用您自己实现的DllMain()函数。
答案 2 :(得分:2)
当你学习编程时,有人会告诉你“发生的第一件事是代码在main
中运行。但这有点像你在学校学习原子时,它们组织得相当好如果你以后去大学的核/粒子物理课,这些简单/严格的规则要详细得多,并不总是适用,等等。
当您链接C或C ++程序时,CRT包含一些类似的代码:
start()
{
CRT_init();
...
Global_Object_Constructors();
...
exit(main());
}
因此初始化由C运行时库本身完成,在它调用main之前。
DLL有一个由DllMain
执行的LoadLibrary()
- 它负责初始化/创建DLL中的全局对象,如果你不使用LoadLibrary()
[例如}自己将DLL加载到内存中]然后你必须确保创建和初始化对象。