VC++全局变量初始化-16.09.26.doc

  1. 1、本文档共7页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
VC全局变量初始化-16.09.26

VC++全局变量 Hanford 2016年09月26日 目 录 第1章 说明 2 1.1 程序启动 2 1.2 强符号、弱符号 2 1.3 动态初始化顺序 3 1.4 exe调用dll 4 1.5 禁用动态初始化 4 1.6 应用实例 5 第1章 说明 1.1 程序启动 参考下面的C++代码: int GetC() { return 2;}; int a; int b = 1; int c = GetC(); int main() { return a+b+c; } 程序载入内存,全局变量a、b、c就完成了静态初始化(static initialization),此时a、b、c的数值分别为0、1、0。 系统会调用入口函数mainCRTStartup,后者会调用_initterm(__xc_a,__xc_z);执行_initterm函数时会调用GetC函数,完成全局变量c的动态初始化(dynamic initialization)。此时a、b、c的数值分别为0、1、2。 mainCRTStartup会接着调用函数main,至此完成程序的启动工作。 注意:C语言里的全局变量只能静态初始化;C++语言里的全局变量才支持动态初始化。 1.2 强符号、弱符号 上面示例代码中的全局变量a没有赋给初始值,它就是弱符号。弱符号全局变量会被编译器初始化为零。 上面示例代码中的全局变量b、c赋予了初始值,它们就是强符号。 弱符号可能会被合并。如:1.cpp、2.cpp里均有弱符号a,那么连接时它们将被当做一个全局变量。又如:1.cpp、2.cpp里均有弱符号a,3.cpp里有强符号a,那么连接时以强符号为准。 强符号是不会被合并的。如:1.cpp、2.cpp里均有强符号a,那么连接时就会出错。 建议:尽量使用强符号,否则可能会产生难以察觉的错误。 1.3 动态初始化顺序 C++代码里,可使用#pragma init_seg来调整动态初始化的顺序。其顺序一共分为52级,如下表所示: #pragma init_seg(.CRT$XIA) #pragma init_seg(.CRT$XIB) ... ... ... #pragma init_seg(.CRT$XIZ) #pragma init_seg(.CRT$XCA) #pragma init_seg(.CRT$XCB) #pragma init_seg(.CRT$XCC) 或 #pragma init_seg(compiler) ... ... ... #pragma init_seg(.CRT$XCL) 或 #pragma init_seg(lib) ... ... ... #pragma init_seg(.CRT$XCU) 或 #pragma init_seg(user) ... ... ... #pragma init_seg(.CRT$XCZ) 上表中,越靠上的段内全局变量越先被动态初始化。如下面的两个cpp文件内容: #pragma init_seg(.CRT$XCC) int C1 = GetC1(); int C2 = GetC2(); #pragma init_seg(.CRT$XCL) int L1 = GetL1(); int L2 = GetL2(); 全局变量C1、C2在段.CRT$XCC里,L1、L2在段.CRT$XCL里,所以C1、C2肯定比L1、L2优先完成动态初始化。 同一段内全局变量的初始化顺序完全无法预料。如:上面C1、C2的动态初始化顺序是无法预料的。 全局变量默认在段.CRT$XCU内,C++库的全局变量在段.CRT$XCC内,MFC库的全局变量在段.CRT$XCL内。所以,编写一个MFC程序并且静态连接MFC库时,C++库的全局变量首先被动态初始化,然后MFC库的全局变量被动态初始化,最后是MFC程序里的全局变量被动态初始化。这样的动态初始化顺序非常重要,因为MFC程序里的全局变量有可能会调用C++库或MFC库里的函数或变量。不调整好顺序就有可能出错。如下面的代码: #include stdio.h #include string #pragma init_seg(.CRT$XCA) std::string s = 123; void main() { puts(s.c_str()); } 如果上述代码静态连接C运行时库,那么在C++库内的全局变量被初始化前,全局变量s就被动态初始化了。结果就是s动态初始化失败,其成员变量全部为零(静态初始化的结果)。 1.4 exe调用dll 上一节的例子,如果动态连接C运行时库(msvcrt.dll),那么全局变量s就能正常动

文档评论(0)

xcs88858 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

版权声明书
用户编号:8130065136000003

1亿VIP精品文档

相关文档