考虑由两个共享库组成的以下设置,它们都使用静态库:
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 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关键字在static.cpp中的a前面,但a只有一个实例。是否有一种方法可以拥有两个a实例,一个用于每个共享库?
发布于 2015-12-20 15:57:16
显然,尽管在static.cpp中有一个静态关键字,但只有一个实例存在。
这是不正确的:存在两个a实例,但实际上只使用了一个实例。
这是因为(与您预期的相反),printB调用了第一个可用的getA (来自libshareda.so的,而不是来自libsharedb.so的)。这是UNIX共享库和Windows DLL之间的一个主要区别。UNIX共享库模拟如果链接是:
clang++ -L. -o main main.cpp shareda.o sharedb.o libstatic.a那么你能做什么来“解决”这个问题呢?
libsharedb.so,可以链接getA以更好地使用自己的getA。getA完全隐藏在libsharedb.so中(就好像它是一个私有实现细节):
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命令行B.事项上源/对象文件和库的顺序,库应该遵循引用它们的对象文件。
https://stackoverflow.com/questions/34381562
复制相似问题