考虑到我在编译单元中有一个静态变量,最后在静态库libA中.然后我有另一个编译单元访问这个变量,最终在一个共享库libB.so(所以libA必须链接到libB).最后,我有一个主要功能也直接从A访问静态变量,并具有对libB的依赖(所以我链接到libA和libB).
我然后观察,静态变量被初始化了两次,即它的构造函数运行两次!这似乎不对.链接器不应该识别两个变量是否相同,并将它们优化为一个?
为了使我的困惑完美,我看到它运行两次与同一个地址!那么也许连接器确实识别了它,但是没有删除static_initialization_and_destruction代码中的第二个调用?
这是一个展示:
ClassA.hpp:
- #ifndef CLASSA_HPP
- #define CLASSA_HPP
- class ClassA
- {
- public:
- ClassA();
- ~ClassA();
- static ClassA staticA;
- void test();
- };
- #endif // CLASSA_HPP
ClassA.cpp:
- #include <cstdio>
- #include "ClassA.hpp"
- ClassA ClassA::staticA;
- ClassA::ClassA()
- {
- printf("ClassA::ClassA() this=%p\n",this);
- }
- ClassA::~ClassA()
- {
- printf("ClassA::~ClassA() this=%p\n",this);
- }
- void ClassA::test()
- {
- printf("ClassA::test() this=%p\n",this);
- }
ClassB.hpp:
- #ifndef CLASSB_HPP
- #define CLASSB_HPP
- class ClassB
- {
- public:
- ClassB();
- ~ClassB();
- void test();
- };
- #endif // CLASSB_HPP
ClassB.cpp:
- #include <cstdio>
- #include "ClassA.hpp"
- #include "ClassB.hpp"
- ClassB::ClassB()
- {
- printf("ClassB::ClassB() this=%p\n",this);
- }
- ClassB::~ClassB()
- {
- printf("ClassB::~ClassB() this=%p\n",this);
- }
- void ClassB::test()
- {
- printf("ClassB::test() this=%p\n",this);
- printf("ClassB::test: call staticA.test()\n");
- ClassA::staticA.test();
- }
TEST.CPP:
- #include <cstdio>
- #include "ClassA.hpp"
- #include "ClassB.hpp"
- int main(int argc,char * argv[])
- {
- printf("main()\n");
- ClassA::staticA.test();
- ClassB b;
- b.test();
- printf("main: END\n");
- return 0;
- }
然后我编译并链接如下:
- g++ -c ClassA.cpp
- ar rvs libA.a ClassA.o
- g++ -c ClassB.cpp
- g++ -shared -o libB.so ClassB.o libA.a
- g++ -c Test.cpp
- g++ -o test Test.cpp libA.a libB.so
输出为:
- ClassA::ClassA() this=0x804a040
- ClassA::ClassA() this=0x804a040
- main()
- ClassA::test() this=0x804a040
- ClassB::ClassB() this=0xbfcb064f
- ClassB::test() this=0xbfcb064f
- ClassB::test: call staticA.test()
- ClassA::test() this=0x804a040
- main: END
- ClassB::~ClassB() this=0xbfcb064f
- ClassA::~ClassA() this=0x804a040
- ClassA::~ClassA() this=0x804a040
有人可以解释这里发生了什么吗?什么是链接器?同一个变量如何初始化两次?
解决方法
您将libA.a包含到libB.so中.通过这样做,libB.so和libA.a都包含ClassA.o,它定义了静态成员.
在您指定的链接顺序中,链接器从静态库libA.a中引用ClassA.o,因此ClassA.o初始化代码在main()之前运行.当访问动态libB.so中的第一个函数时,将运行libB.so的所有初始化程序.由于libB.so包含ClassA.o,所以ClassA.o的静态初始化程序必须运行(再次).
可能的修复:
>不要将ClassA.o放在libA.a和libB.so中.
- g++ -shared -o libB.so ClassB.o
>不要使用这两个库;不需要libA.a
- g++ -o test Test.cpp libB.so
应用上述任一修复问题:
- ClassA::ClassA() this=0x600e58
- main()
- ClassA::test() this=0x600e58
- ClassB::ClassB() this=0x7fff1a69f0cf
- ClassB::test() this=0x7fff1a69f0cf
- ClassB::test: call staticA.test()
- ClassA::test() this=0x600e58
- main: END
- ClassB::~ClassB() this=0x7fff1a69f0cf
- ClassA::~ClassA() this=0x600e58