每个图书馆将推出包括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
:默认符号可见性规则。 其他 模块可以使用全局符号和弱符号;本地模块中的引用可以通过其他 模块中的定义插入到 中。
关于SysV ABI:
当解析符号引用时, 动态连接器检查与广度优先搜索的符号表。 也就是说,它首先查看可执行程序 程序本身的符号表,然后在 DT_NEEDED
条目的符号表(按顺序),然后在第二级DT_ NEEDED
条目等等。
如果这不符合预期,则在符号上使用STV_HIDDEN
可防止它在共享对象外部可见。
相比之下,在Windows上,一个符号总是从给定的DLL中导入,并且这些符号默认情况下不会导出到其他DLL。
如果你不能得到答案我想你可以通过改变1库中的全局变量并从第二个库检查它的值来执行一个简单的测试。 –