突然想到以前遇到的一个问题,动态链接库加载的问题。如果有多个动态链接库里面都有相同符号的函数,程序在执行时会优先执行那个动态链接库中的函数呢?

 

先给结论

动态链接库加载顺序:

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)