跨C++文件和库对静态工具举办初始化
当前位置:以往代写 > C/C++ 教程 >跨C++文件和库对静态工具举办初始化
2019-06-13

跨C++文件和库对静态工具举办初始化

跨C++文件和库对静态工具举办初始化

副标题#e#

假期凡是是个回首已往的好时候。这里就是我正在思考的上个月使我发生"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


#p#副标题#e#

然后获得的功效如下:

./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]

    关键字:

在线提交作业