用C ++编写:
静态库" A"定义全局变量foo。
" B"和" C"两个动态库都依赖于A,因此(静态地)与A链接。
然后B和C最终加载到同一个进程中 (例如:应用程序加载B和C)。
如果我们在windows环境中,我们将获得两个不同的foo实例,一个在B中,一个在C中,如下所述:
Shared global variable in C++ static library
Linux环境怎么样?
上下文: 我们目前正在将一个Windows项目移植到linux
答案 0 :(得分:1)
每个库都将包含A的副本。但是,在运行时,该过程的所有组件都只使用一个。
// h.h
extern int a;
void b(void);
void c(void);
// a.c
#include "h.h"
int a = 0;
// b.c
#include <stdio.h>
#include "h.h"
void b(void)
{
printf("%i\n", a++);
}
// c.c
#include <stdio.h>
#include "h.h"
void c(void)
{
printf("%i\n", a++);
}
//main.c
#include <stdio.h>
#include "h.h"
int main()
{
b();
c();
}
#Makefile
main: libxc.so libxb.so
cc -o main main.c -L. -lxc -lxb
libxb.so:
cc -fPIC -shared a.c b.c -o libxb.so
libxc.so:
cc -fPIC -shared a.c c.c -o libxc.so
$make $ LD_LIBRARY_PATH=. ./main 0 1
来自libxa.so
的符号表:
53: 000000000020098c 4 OBJECT GLOBAL DEFAULT 24 a
来自libxc.so
:
53: 000000000020098c 4 OBJECT GLOBAL DEFAULT 24 a
默认可见性为STV_DEFAULT
,根据LSB:
STV_DEFAULT
:符号STV_DEFAULT
的可见性 属性由符号的绑定类型指定。那是, 全局和弱势符号在其外部可见 确定 组件(可执行文件或共享对象)。本地符号是 隐藏,如下所述。全局和弱符号也是 可抢占的,也就是说,它们可能会被相同的定义所取代 在另一个组件中命名。
man 5 elf
:
STV_DEFAULT
:默认符号可见性规则。 Globa和弱符号可供其他人使用 模块;本地模块中的引用可以 被其他人的定义所插入 模块。
关于SysV ABI:
解析符号引用时, 动态链接器使用广度优先搜索检查符号表。 也就是说,它首先查看可执行文件的符号表 程序本身,然后在符号表
DT_NEEDED
条目(按顺序),然后是第二级DT _NEEDED
条目,等等。
如果这不符合预期,那么在符号上使用STV_HIDDEN
会阻止它在共享对象外部可见。
相比之下,在Windows上,始终从给定的DLL导入符号,并且默认情况下,符号不会导出到其他DLL。