c – 静态变量初始化两次

前端之家收集整理的这篇文章主要介绍了c – 静态变量初始化两次前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
考虑到我在编译单元中有一个静态变量,最后在静态库libA中.然后我有另一个编译单元访问这个变量,最终在一个共享库libB.so(所以libA必须链接到libB).最后,我有一个主要功能也直接从A访问静态变量,并具有对libB的依赖(所以我链接到libA和libB).

我然后观察,静态变量被初始化了两次,即它的构造函数运行两次!这似乎不对.链接器不应该识别两个变量是否相同,并将它们优化为一个?

为了使我的困惑完美,我看到它运行两次与同一个地址!那么也许连接器确实识别了它,但是没有删除static_initialization_and_destruction代码中的第二个调用

这是一个展示:

ClassA.hpp:

  1. #ifndef CLASSA_HPP
  2. #define CLASSA_HPP
  3.  
  4. class ClassA
  5. {
  6. public:
  7. ClassA();
  8. ~ClassA();
  9. static ClassA staticA;
  10.  
  11. void test();
  12. };
  13.  
  14. #endif // CLASSA_HPP

ClassA.cpp:

  1. #include <cstdio>
  2. #include "ClassA.hpp"
  3.  
  4. ClassA ClassA::staticA;
  5.  
  6. ClassA::ClassA()
  7. {
  8. printf("ClassA::ClassA() this=%p\n",this);
  9. }
  10.  
  11. ClassA::~ClassA()
  12. {
  13. printf("ClassA::~ClassA() this=%p\n",this);
  14. }
  15.  
  16. void ClassA::test()
  17. {
  18. printf("ClassA::test() this=%p\n",this);
  19. }

ClassB.hpp:

  1. #ifndef CLASSB_HPP
  2. #define CLASSB_HPP
  3.  
  4. class ClassB
  5. {
  6. public:
  7. ClassB();
  8. ~ClassB();
  9.  
  10. void test();
  11. };
  12.  
  13. #endif // CLASSB_HPP

ClassB.cpp:

  1. #include <cstdio>
  2. #include "ClassA.hpp"
  3. #include "ClassB.hpp"
  4.  
  5. ClassB::ClassB()
  6. {
  7. printf("ClassB::ClassB() this=%p\n",this);
  8. }
  9.  
  10. ClassB::~ClassB()
  11. {
  12. printf("ClassB::~ClassB() this=%p\n",this);
  13. }
  14.  
  15. void ClassB::test()
  16. {
  17. printf("ClassB::test() this=%p\n",this);
  18. printf("ClassB::test: call staticA.test()\n");
  19. ClassA::staticA.test();
  20. }

TEST.CPP:

  1. #include <cstdio>
  2. #include "ClassA.hpp"
  3. #include "ClassB.hpp"
  4.  
  5. int main(int argc,char * argv[])
  6. {
  7. printf("main()\n");
  8. ClassA::staticA.test();
  9. ClassB b;
  10. b.test();
  11. printf("main: END\n");
  12.  
  13. return 0;
  14. }

然后我编译并链接如下:

  1. g++ -c ClassA.cpp
  2. ar rvs libA.a ClassA.o
  3. g++ -c ClassB.cpp
  4. g++ -shared -o libB.so ClassB.o libA.a
  5. g++ -c Test.cpp
  6. g++ -o test Test.cpp libA.a libB.so

输出为:

  1. ClassA::ClassA() this=0x804a040
  2. ClassA::ClassA() this=0x804a040
  3. main()
  4. ClassA::test() this=0x804a040
  5. ClassB::ClassB() this=0xbfcb064f
  6. ClassB::test() this=0xbfcb064f
  7. ClassB::test: call staticA.test()
  8. ClassA::test() this=0x804a040
  9. main: END
  10. ClassB::~ClassB() this=0xbfcb064f
  11. ClassA::~ClassA() this=0x804a040
  12. 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中.

  1. g++ -shared -o libB.so ClassB.o

>不要使用这两个库;不需要libA.a

  1. g++ -o test Test.cpp libB.so

应用上述任一修复问题:

  1. ClassA::ClassA() this=0x600e58
  2. main()
  3. ClassA::test() this=0x600e58
  4. ClassB::ClassB() this=0x7fff1a69f0cf
  5. ClassB::test() this=0x7fff1a69f0cf
  6. ClassB::test: call staticA.test()
  7. ClassA::test() this=0x600e58
  8. main: END
  9. ClassB::~ClassB() this=0x7fff1a69f0cf
  10. ClassA::~ClassA() this=0x600e58

猜你在找的C&C++相关文章