导读:
Hi, I’m George Mileka and I work on the Visual C++ libraries team. My team owns the CRT, ATL, MFC and STL…
One subject I have always been interested in is the startup code and initialization. The subject got even more challenging as we started supporting mixing native and managed code in our binaries.
Today I will talk about how the CRT initializes global states in the native world…
By default, the linker includes the CRT library which provides its own startup code. The CRT startup code initializes the CRT library, calls global initializers, and finally calls user-provided “main()” function (for console applications).
Now, consider the following code:
int func(void)
{
return 3;
}
int gi = func();
int main()
{
return gi;
}
According to the C/C++ standard, func() must be called before main() is executed. But who calls it?
An easy way to know, is to set a breakpoint in func(), start debugging the application and look at the stack! Luckily, the CRT code ships with VS!
Browsing the functions on the stack, you will find that the CRT is simply looping through a list of function pointers, calling each one as it goes through them. Those functions are either ones like func() or constructors for class instances…
So, where does the CRT get that list from?
There is a contract between the CRT and VC++ Compiler:
When the VC++ compiler sees a global initializer, it generates a dynamic initializer in the .CRT$XCU section (note that the CRT is the section name and XCU is the group name). You can look at those dynamic initializers by running “dumpbin /all main.obj”, and then looking at the .CRT$XCU section (when main.cpp is compiled as a cpp file, not a c file). It will have something like this:
SECTION HEADER #C
.CRT$XCU name
.
.
RELOCATIONS #C
Symbol Symbol
Offset Type Applied To Index Name
-------- ---------------- ----------------- -------- ------
00000000 DIR32 00000000 26 ??__Egi@@YAXXZ(void __cdecl `dynamic initializer for 'gi'(void))
- CRT defines two pointers;
o __xc_a in .CRT$XCA
o __xc_z in .CRT$XCZ
Both groups do not have any other symbols defined except __xc_a and __xc_z.
Now –when the linker reads various .CRT groups, it combines them in one section and orders them alphabetically. This means that the user-defined global initializers (which the VC++ compiler puts in .CRT$XCU) will always come after .CRT$XCA and before .CRT$XCZ. So, it should look something like:
.CRT$XCA
__xc_a
.CRT$XCU
Pointer to Global Initializer 1
Pointer to Global Initializer 2
.CRT$XCZ
__xc_z
So, the CRT library can use both __xc_a and __xc_z to determine the start and end of the global initializers list (array) because of how they are laid out in memory once the image is loaded.
Please, send any questions, comments or feedback our way! We’ll be happy to address them!
George Mileka
Visual C++ Libraries Team
posted on 2006-12-14 17:53 sunrack阅读(34) 评论(0) 编辑收藏所属分类: Visual C++ 2005
新用户注册 刷新评论列表
标题
姓名
主页
Email (只有博主才能看到)邮件地址无效
请输入验证码 验证码 *
看不清,换一张
内容(请不要发表任何与政治相关的内容) 请输入评论内容
Remember Me?
登录 使用高级评论 新用户注册 返回页首 恢复上次提交
[使用Ctrl+Enter键可以直接提交]
向地震灾区捐赠爱心
所属分类的其他文章:
· 在 C# 中动态调用 native dll 的导出函数· 单件的标准形式· Visual C++ 如何:在各种字符串类型之间进行转换· C++实现单件· VC预处理指令与宏定义的妙用· Visual C++ 2005 中的XML注释· 预编译头文件· VC++2005 (CLI-C++) 中使用Pwlib和Opal时,运行时报错_CrtIsValidHeapPointer问题的解决!!· Converting Managed Extensions for C++ Projects from Pure Intermediate Language to Mixed Mode· Persisting View State Update, Using Managed Extensions in a DLL
博客园首页 社区
本文转自
http://www.cnblogs.com/sunrack/articles/592393.html