仔细想想,分析一下,各种可能性都有,得看这些库和可执行文件是怎么编译链接的才行,具体看下面的各种case。
同时,测试的code里在dynamic里加上了同名的函数,看看函数会有什么表现。
假设有如下文件(code见
Gist
):
common.h
common.cpp // 生成libcommon.a
dynamic1.h
dynami1.cpp // 生成libdynamic1.so
dynamic2.h
dynamic2.cpp // 生成libdynamic2.so
main.cpp // 生成main
生成
libcommon.a
总是这么编译:
g++ -g -Wall -Wextra -c -o common.o common.cpp
ar rcs libcommon.a common.o
Case 0
: 动态链接库不link .a,main直接link .so,生成main的时候也不link .a
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic1.so dynamic1.cpp
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic2.so dynamic2.cpp
g++ -DDIRECT_CALL_SO -o main main.cpp -L. -ldynamic1 -ldynamic2
这种情况结果显然是4,link时出错,找不到.a里的函数。
Case 1
: 动态链接库不link .a,main直接link .so,生成main的时候link .a
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic1.so dynamic1.cpp
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic2.so dynamic2.cpp
g++ -DDIRECT_CALL_SO -o main main.cpp -L. -ldynamic1 -ldynamic2 -lcommon
LD_LIBRARY_PATH=. ./main
这种情况下执行的结果是2,link时没错,执行时看到的也是同一个变量。
GetInt()
返回值是1,它依赖于-l的顺序,如果
-ldynamic2
在前,返回值就是2了。
Case 2
: 动态链接库link .a,main直接link .so,生成main的时候无所谓要不要link .a
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic1.so dynamic1.cpp -L. -lcommon
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic2.so dynamic2.cpp -L. -lcommon
g++ -DDIRECT_CALL_SO -o main main.cpp -L. -ldynamic1 -ldynamic2
LD_LIBRARY_PATH=. ./main
执行结果同上
Case 3
: 动态链接库不link .a,main不链接.so,通过
dlopen()
调用so,无所谓链接.a
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic1.so dynamic1.cpp
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic2.so dynamic2.cpp
g++ -o main main.cpp -ldl [-L. -lcommon]
LD_LIBRARY_PATH=. ./main
执行结果是4,
dlopen
的时候找不到
GetGlobalStatic()
。
Case 4
: 动态链接库link .a,main不链接.so,通过
dlopen()
调用so(不用
RTLD_GLOBAL
),无所谓链接.a
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic1.so dynamic1.cpp -L. -lcommon
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic2.so dynamic2.cpp -L. -lcommon
g++ -o main main.cpp -ldl
LD_LIBRARY_PATH=. ./main
执行结果是3,各有各自的变量。
GetInt()
返回的也是各自的变量。
Case 5
: 动态链接库link .a,main不链接.so,通过
dlopen()
调用so(使用
RTLD_GLOBAL
),无所谓链接.a
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic1.so dynamic1.cpp -L. -lcommon
g++ -g -Wall -Wextra -fPIC -shared -o libdynamic2.so dynamic2.cpp -L. -lcommon
g++ -DUSE_RTLD_GLOBAL -o main main.cpp -ldl -L. -lcommon
LD_LIBRARY_PATH=. ./main
执行结果变成2了,执行时看到了同一个变量。
GetInt()
返回的仍然是各自的变量。
看了这么多case,结果1怎么没有出现呢?别急,如果编译的时候全部编译在一起:
g++ -DDIRECT_CALL_SO -o main main.cpp dynamic1.cpp dynamic2.cpp common.cpp
就出错了,
GetInt()
重定义。
对于不同so link的.a里的变量:
如果是直接link的,总是用同一个变量。仔细想想肯定是这样,否则一定会出现multiple definition
如果是dlopen,它依赖
dlopen()
的flag:
如果是
RTLD_LOCAL
(默认),各个so会使用各自的.a里的变量。
如果用
RTLD_GLOBAL
,就跟直接link一样,用同一个变量了。