静态变量初始化两次 [英] Static variable is initialized twice

查看:76
本文介绍了静态变量初始化两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一下,我在编译单元中有一个静态变量,该变量最终在 static 库libA中.然后,我有另一个编译单元访问此变量,该编译单元最终在 shared 库libB.so中(因此libA必须链接到libB中).最后,我有一个主要功能,也可以直接从A中访问与libB有依赖关系的静态变量(因此,我链接到libA libB).

Consider I have a static variable in a compilation unit which ends up in a static library libA. I then have another compilation unit accessing this variable which ends up in a shared library libB.so (so libA must be linked into libB). Finally I have a main function also accessing the static variable from A directly and having a dependency to libB (so I link against libA and libB).

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

I then observe, that the static variable is initialized twice, i.e. its constructor is run twice! This doesn't seem to be right. Shouldn't the linker recognize both variables to be the same and optimize them as one?

为了使我的困惑更加完美,我看到它用相同的地址运行了两次!那么也许链接器 did 可以识别它,但是没有删除static_initialization_and_destruction代码中的第二个调用吗?

To make my confusion perfect, I see it is run twice with the same address! So maybe the linker did recognize it, but did not remove the second call in the static_initialization_and_destruction code?

这是一个展示柜:

ClassA.hpp:

ClassA.hpp:

#ifndef CLASSA_HPP
#define CLASSA_HPP

class ClassA
{
public:
    ClassA();
    ~ClassA();
    static ClassA staticA;

    void test();
};

#endif // CLASSA_HPP

ClassA.cpp:

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:

ClassB.hpp:

#ifndef CLASSB_HPP
#define CLASSB_HPP

class ClassB
{
public:
    ClassB();
    ~ClassB();

    void test();
};

#endif // CLASSB_HPP

ClassB.cpp:

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;
}

然后我按如下所示进行编译和链接:

I then compile and link as follows:

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

有人可以解释一下这是怎么回事吗?链接器在做什么?相同变量如何初始化两次?

Can somebody please explain what is going on here? What is the linker doing? How can the same variable be initialized twice?

推荐答案

您正在将 libA.a 包含在 libB.so 中.这样, libB.so libA.a 都包含定义静态成员的 ClassA.o .

You are including libA.a into libB.so. By doing this, both libB.so and libA.a contain ClassA.o, which defines the static member.

按照您指定的链接顺序,链接器从静态库 libA.a 中提取 ClassA.o ,因此, ClassA.o 初始化代码在 main()之前运行.当访问动态 libB.so 中的第一个函数时,将运行 libB.so 所有初始化程序.由于 libB.so 包括 ClassA.o ,因此必须再次运行 ClassA.o 的静态初始化程序.

In the link order you specified, the linker pulls in ClassA.o from the static library libA.a, so ClassA.o initialization code is run before main(). When the first function in the dynamic libB.so is accessed, all initializers for libB.so are run. Since libB.so includes ClassA.o, ClassA.o's static initializer must be run (again).

可能的解决方法:

  1. 不要将ClassA.o放到libA.a和libB.so中.

  1. Don't put ClassA.o into both libA.a and libB.so.

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

  • 不要同时使用这两个库;不需要libA.a.

  • Don't use both libraries; libA.a is not needed.

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

  • 应用以上任一方法均可解决问题:

    Applying either of the above fixes the problem:

    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
    

    这篇关于静态变量初始化两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆