每個圖書館將推出包括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庫中的全局變量並從第二個庫檢查它的值來執行一個簡單的測試。 –