考虑我在编译单元中有一个静态变量,它最终存在于静态库libA中.然后我有另一个编译单元访问这个变量,最终在一个共享库libB.so(所以libA必须链接到libB).最后我有一个main函数也直接从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
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
ClassB.hpp:
#ifndef CLASSB_HPP
#define CLASSB_HPP
class ClassB
{
public:
ClassB();
~ClassB();
void test();
};
#endif // CLASSB_HPP
Run Code Online (Sandbox Code Playgroud)
ClassB.cpp: …
假设我们有:
在f1.c
#include <stdio.h>
static int x = 10;
void f1() {
printf("f1.c : %d\n", x);
}
Run Code Online (Sandbox Code Playgroud)
main.c中
extern void f1();
int main(int argc, char **argv) {
f1();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我们将编译和读取两个ELF文件符号表(rel.ELF和exec ELF):
$> gcc -c *.c
$> readelf -s f1.o | grep x
Num: Value Size Type Bind Vis Ndx Name
5: 0000000000000000 4 OBJECT LOCAL DEFAULT 3 x
$> gcc *.o
$> readelf -s a.out | grep x
Num: Value Size Type Bind Vis Ndx Name
38: 0000000000601038 …Run Code Online (Sandbox Code Playgroud)