当前位置:首页 >> 编程开发 >> Visual C++ >> 内容

跨C++文件和库对静态对象进行初始化

时间:2015/5/19 21:32:14 作者:平凡之路 来源:xuhantao.com 浏览:

假期通常是个回顾过去的好时候。这里就是我正在思考的上个月使我产生"ah-hah"瞬间的一个 问题。

问题:

当你编译下面的C++程序的时候,你可能认为模块(module)中的对象会先编译并先初始 化。

这种假设可能得不到预期的结果。

X.h :

#include <string>

using namespace std;    // 译者注: 加上这行

class CObjet {

 public:

    static const string STRINGX;

};

X.cpp:

#include <X.h>

using namespace std;    // 译者注: 这行可以不要

const string CObjet::STRINGX = "001";

Y.cpp:

#include <iostream>

#include <X.h>

const string STRINGY= CObjet::STRINGX;

int main () {

cout << "CObjet::STRINGX [" <<CObjet::STRINGX << "]" << endl;

cout << "STRINGY [" <<  STRINGY << "]" << endl;

return 0;

}

如果用下面的命令来编译:

xlC -c -I./ X.cpp -o X.o

xlC -c -I./ Y.cpp -o Y.o

xlC -o binary X.o Y.o

然后得到的结果如下:

./binary

CObjet::STRINGX [001]

STRINGY []    // 译者注: 该结果是AIX平台的, Linux平台可能会Segmentation fault

从这个结果来看,STRINGY并没有像预期的那样初始化为STRINGX

原因:

STRINGX和STRINGY是全 局静态对象。STRINGY的初始化取决于STRINGX的初始化。两者定义在不同的源文件中。

虽然C++语言规范规 定了同一个文件中这类对象的初始化顺序(按照定义的顺序),但并没有规定在跨文件或者库时这些对象的初始 化顺序。

因此虽然模块X.o先编译, STRINGX仍可能会在STRINGY之后初始化, 这就形成了一个空的 STRINGY.

取决于编译器和操作系统缓存中当前的值, STRINGY甚至可能包含了垃圾数据并导致程序运行时崩 溃。

解决方案:

为了解决这个问题,一些开发者将每个非局部静态对象都移动到自己的函数中,并 声明为静态的。并让这些函数返回这个静态对象的引用, 然后按照自己期望的对象初始化顺序来调用这些函数 .虽然这通常是个可移植的方法,但是这需要修改代码。

XL C/C++编译器可以使得这项工作变得简单。你可以使用-qpriority或-qmkshrobj=priority(译者注: linux上只有-qmkshrobj形式) 或 -Wm,-c选项来指定定义在不同文件或者库中的静态对象的初始化顺序。这些 选项会给每个模块赋予一个优先级值,然后根据该值来控制对象的初始化顺序。

包含主函数main()的模块通常优先级为0. 值越小表示优先级越高,在上面的例子中,可以在编译X.o的时候 指定-qpriority=-100从而保证X.o中的对象在Y.o对象初始化之前初始化。

同样的,如果你想把X.o创建到一个共享库中,那么可以在创建该库的时候指定-qmkshrobj=-100。

即,你可以用下面的命令来编译:

xlC -c -I./ -qpriority=-100 X.cpp -o X.o

xlC -c -I./ Y.cpp -o Y.o

xlC -o binary X.o Y.o

或者, 创建共享库:

xlC -c -I./ X.cpp -o X.o

xlC -c -I./ Y.cpp -o Y.o

xlC -qmkshrobj=-100 -o libX.so X.o

xlC -o binary -btrl Y.o -L. -lX

这时执行程序就会得到如下结果:

./binary

CObjet::STRINGX [001]

STRINGY [001]

相关文章
  • 没有相关文章
共有评论 0相关评论
发表我的评论
  • 大名:
  • 内容:
  • 徐汉涛(www.xuhantao.com) © 2024 版权所有 All Rights Reserved.
  • 部分内容来自网络,如有侵权请联系站长尽快处理 站长QQ:965898558(广告及站内业务受理) 网站备案号:蒙ICP备15000590号-1