考虑以下由两个共享库组成的设置,它们都使用静态库:
static.cpp
#include "static.h"
static int a = 0;
int getA()
{
return a++;
}
static.h
#pragma once
int getA();
shareda.cpp
#include <iostream>
#include "shareda.h"
#include "static.h"
void printA()
{
std::cout << getA() << std::endl;
}
shareda.h
#pragma once
void printA();
sharedb.cpp
#include <iostream>
#include "sharedb.h"
#include "static.h"
void printB()
{
std::cout << getA() << std::endl;
}
sharedb.h
#pragma once
void printB();
main.cpp
#include "shareda.h"
#include "sharedb.h"
int main()
{
printA();
printA();
printB();
printA();
printB();
return 0;
}
我使用以下命令编译并运行了这些文件(使用从源代码编译的 Clang 3.8.0 和带有 GNU ld 2.25 的 64 位 Debian):
clang++ -c static.cpp -o static.o -fPIC
ar rcs libstatic.a static.o
clang++ -c shareda.cpp -o shareda.o -fPIC
clang++ -shared -o libshareda.so shareda.o libstatic.a
clang++ -c sharedb.cpp -o sharedb.o -fPIC
clang++ -shared -o libsharedb.so sharedb.o libstatic.a
clang++ -L. -lshareda -lsharedb -o main main.cpp
LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./main
令我惊讶的是,输出如下:
0
1
2
3
4
我的期望是这样的:
0
1
0
2
1
显然,尽管在 static.cpp 中 a
前面有 static
关键字,但只有一个 a
实例存在。有没有办法让 a
的两个实例,每个共享库一个?
最佳答案
Apparently, despite the static keyword in front of a in static.cpp, only one instance of a exists.
那是不正确:a
存在两个实例,但实际只使用了一个。
那之所以发生,是因为(与您的预期相反)printB
调用了第一个 getA
可用(来自 libshareda.so
的那个,而不是来自 libsharedb.so
的那个)。这是 UNIX 共享库和 Windows DLL 之间的一个主要区别。 UNIX 共享库模拟如果您的链接是:
clang++ -L. -o main main.cpp shareda.o sharedb.o libstatic.a
那么你能做些什么来“解决”这个问题呢?
- 您可以使用
-Bsymbolic
链接libsharedb.so
以更喜欢它自己的getA
。 您可以将
getA
完全隐藏在libsharedb.so
中(就像它是私有(private)实现细节一样):clang++ -c -fvisibility=hidden -fPIC static.cpp ar rcs libstatic.a static.o clang++ -shared -o libsharedb.so sharedb.o libstatic.a
- 您可以使用链接器版本脚本获得类似的结果。
附言您的链接命令:
clang++ -L. -lshareda -lsharedb -o main main.cpp
完全倒退。应该是:
clang++ -L. -o main main.cpp -lshareda -lsharedb
源/目标文件和库在命令行上的顺序 matters ,并且库应该遵循引用它们的目标文件。
关于c++ - 共享库的静态库中静态变量的单独实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34381562/