这是C++代码:
一个静态库"A"定义了全局变量foo。
"B"和"C"是两个动态库,都依赖于A,因此会与A链接(静态链接)。
然后B和C最终加载到同一进程中(例如:应用程序加载B和C)。
如果我们在Windows环境下运行,则会得到两个不同的foo实例,一个在B中,一个在C中,如此清楚地解释在这里:
那么在Linux环境下呢?
背景: 我们目前正在将Windows项目移植到Linux。
这是C++代码:
一个静态库"A"定义了全局变量foo。
"B"和"C"是两个动态库,都依赖于A,因此会与A链接(静态链接)。
然后B和C最终加载到同一进程中(例如:应用程序加载B和C)。
如果我们在Windows环境下运行,则会得到两个不同的foo实例,一个在B中,一个在C中,如此清楚地解释在这里:
那么在Linux环境下呢?
背景: 我们目前正在将Windows项目移植到Linux。
// 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
:默认的符号可见性规则。
全局和弱符号可以供其他模块使用;本地模块中的引用可以被其他模块中的定义替换。DT_NEEDED
条目(按顺序),然后查看第二级DT_NEEDED
条目,以此类推。STV_HIDDEN
可以防止该符号在共享对象之外被看到。