突然想到以前遇到的一个问题,动态链接库加载的问题。如果有多个动态链接库里面都有相同符号的函数,程序在执行时会优先执行那个动态链接库中的函数呢?
先给结论
动态链接库加载顺序:
1.可执行档同目录下的动态链接库;
2.编译时指定的动态链接库位置;
3.运行可执行档前使用LD_LIBRARY_PATH指定的动态链接库位置;
4./etc/ld.so.conf中指定的动态链接库位置;
5./lib中的动态链接库
6./usr/lib中的动态链接库
实验用到的源文件、头文件和CMakeList
hello.h
#ifndef __HELLO_H__
#define __HELLO_H__
void hello(void);
#endif
hello1.c
#include "hello.h"
#include <stdio.h>
void hello(void)
{
printf("This is hello 1!\n");
}
hello2.c
#include "hello.h"
#include <stdio.h>
void hello(void)
{
printf("This is hello 1!\n");
}
main.c
#include "hello.h"
#include <stdio.h>
void main(void)
{
hello();
}
CMakeList.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
GET_FILENAME_COMPONENT(ROOT_PATH ${CMAKE_SOURCE_DIR}/ REALPATH)
PROJECT (HELLO)
SET(SRC_LIST main.c)
SET(DYNAMIC_LIST1 hello1.c)
SET(DYNAMIC_LIST2 hello2.c)
INCLUDE_DIRECTORIES(${ROOT_PATH})
ADD_LIBRARY(hello1 SHARED ${DYNAMIC_LIST1})
ADD_LIBRARY(hello2 SHARED ${DYNAMIC_LIST2})
LINK_DIRECTORIES(${ROOT_PATH}/build/lib)
LINK_DIRECTORIES(${ROOT_PATH}/build/libs)
ADD_EXECUTABLE(main ${SRC_LIST})
TARGET_LINK_LIBRARIES(main hello1)
实验一:编译时不指定动态链接库位置
编译后直接运行输出:This is hello 1!
交换libhello1.so和libhello2.so,运行输出:This is hello 2!
见test1.log
实验二:编译时指定动态链接库位置
将libhello1.so和libhello2.so分别放在lib和libs文件夹中并都改名为libhello1.so,运行发现
LINK_DIRECTORIES(lib)/LINK_DIRECTORIES(libs)的顺序会影响选择动态链接库的顺序,优先加载排在前面的动态链接库。
见test2.log
实验三:编译时不指定动态链接库位置,运行前用LD_LIBRARY_PATH指定
将libhello1.so和libhello2.so分别放在lib和libs文件夹中并都改名为libhello1.so(并作交换),运行发现优先加载最早填入LD_LIBRARY_PATH。
见test3.log
实验四:编译时指定动态链接库位置,运行前用LD_LIBRARY_PATH指定
将libhello1.so和libhello2.so分别放在lib和libs文件夹中并都改名为libhello1.so(并作交换),再加入LD_LIBRARY_PATH,发现优先加载编译程序时指定的动态链接库,找不到再加载LD_LIBRARY_PATH中的动态链接库
见test4.log
实验五:编译时指定动态链接库位置,但是执行档目录下有同名动态链接库
优先加载执行档同名路径下的动态链接库
见test5.log
查看编译时是否指定动态链接库位置
$readelf -d main
l 编译时没有指定动态链接库位置
yangfan@ubuntu:~/Workspace/CMake_dynamic/build$ readelf -d main
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libhello1.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/yangfan/Workspace/CMake_dynamic/build]
l 编译时指定动态链接库位置
yangfan@ubuntu:~/Workspace/CMake_dynamic/build$ readelf -d main
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libhello1.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/yangfan/Workspace/CMake_dynamic/build/lib:/home/yangfan/Workspace/CMake_dynamic/build]
编译时指定动态链接库位置的话Library rpath一般会有多于一个的路径
查看程序将会加载哪个动态链接库
$ldd main
yangfan@ubuntu:~/Workspace/CMake_dynamic$ ldd main
linux-vdso.so.1 => (0x00007fff1aff6000)
libhello1.so => /home/yangfan/Workspace/CMake_dynamic/build/libhello1.so (0x00007f2f03e38000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2f03a50000)
/lib64/ld-linux-x86-64.so.2 (0x000055d2cfdfa000)