Linux 动态库跨库调用 symbol lookup error原因详解

打印 上一主题 下一主题

主题 530|帖子 530|积分 1605

1、起因

今天调试了一个步伐,发现symbol lookup error,本想网上找一下方法解决算了怎料找了半天都没写根因的文章,好不容易找到一篇雷同的,竟然要收费!
自此打算分析一下,symbol lookup error无非就是链接和库的查找问题。
先说我的应用场景(简化):
主步伐(main)调用A(libefg.so)库,A库调用B库(libabc.so),main没有直接调用B库。
运行main步伐的时候尽然报symbol lookup error!明明我的libabc.so也在同级目次。
  1. ./main: symbol lookup error: ./libefg.so: undefined symbol: _Z9print_abcv
复制代码
2、分析

2.1 代码布局

编写B库libabc.so,包含test_abc.cpp和test_abc.h
2.1.1 libabc.so

  1. // test_abc.cpp
  2. #include "test_abc.h"
  3. void print_abc()
  4. {
  5.         printf("abc\n");
  6. }
复制代码
  1. // test_abc.h
  2. #ifndef __TEST_ABC__
  3. #define __TEST_ABC__ 1
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. void print_abc();
  7. #endif /* ifndef __TEST_ABC__ */
复制代码
2.1.2 libefg.so

  1. // test_efg.cpp
  2. #include "test_efg.h"
  3. void print_def()
  4. {
  5.         printf("output def\n");
  6.         print_abc();
  7. }
复制代码
  1. // test_efg.h
  2. #ifndef __TEST_EFG__
  3. #define __TEST_EFG__ 1
  4. #include "test_abc.h"
  5. void print_def();
  6. #endif /* ifndef __TEST_EFG__ */
复制代码
2.1.3 main

  1. // main.cpp
  2. #include "test_efg.h"
  3. int main(int argc, char *argv[])
  4. {
  5.         printf("main...\n");
  6.         print_def();
  7.         return 0;
  8. }
复制代码
2.2 代码编译

  1. cat Makefile
  2. all:
  3.         g++ test_abc.cpp -shared -fPIC -o libabc.so
  4.         g++ test_efg.cpp -shared -fPIC -o libefg.so
  5.         g++ main.cpp -L. -Wl,-rpath=./ -lefg -o main -labc
  6. .PHONY: clean
  7. clean:
  8.         rm -rf libabc.so libefg.so main
复制代码
编译完成后运行报错
  1. main...
  2. output def
  3. ./main: symbol lookup error: ./libefg.so: undefined symbol: _Z9print_abcv
复制代码
纳闷了,明明libabc.so 和libefg.so都在本目次,不可能找得到libefg找不到libabc。
利用ldd检察二进制文件main,看看是不是找不到libabc
  1. ldd ./main
  2.         linux-vdso.so.1 (0x00007ffd069b1000)
  3.         libefg.so => ./libefg.so (0x00007f0c19bc7000)
  4.         libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0c195b7000)
  5.         /lib64/ld-linux-x86-64.so.2 (0x00007f0c199a8000)
复制代码
原来不但是找不到,而是压根没有libabc.so,可以看到libefg.so是可以认到的了,难怪没有abc的符号,再次确认了一下-labc也是已经加入了。
这次尝试去掉-labc看看能否编译通过
  1. g++ main.cpp -L. -Wl,-rpath=./ -lefg -o main
复制代码
竟然毫无压力的通过了。所以abc的符号在libefg上。
我们再回头看看libefg的编译参数
  1. g++ test_efg.cpp -shared -fPIC -o libefg.so
复制代码
这也没提醒我们链接libabc啊,因此尝试让libefg加上libabc的依赖
  1. g++ test_efg.cpp -shared -fPIC -o libefg.so -Wl,-rpath=./ -L. -labc
复制代码
再次整编译,运行正常!
2.3 CMake

以下写法是可以天生库和执行文件,但是运行还是堕落。
  1. cmake_minimum_required(VERSION 2.8)
  2. set(name cmain)
  3. project(name)
  4. link_directories(${CMAKE_CURRENT_SOURCE_DIR})
  5. ## add libabc
  6. add_library(abc SHARED test_abc.cpp)
  7. ## add libefg
  8. add_library(efg SHARED test_efg.cpp)
  9. ## add main
  10. add_executable(${name} main.cpp)
  11. target_link_libraries(${name} efg abc)
复制代码
改为以下的写法,libefg增长libabc的支持后正常
  1. cmake_minimum_required(VERSION 2.8)
  2. set(name cmain)
  3. project(name)
  4. link_directories(${CMAKE_CURRENT_SOURCE_DIR})
  5. ## add libabc
  6. add_library(abc SHARED test_abc.cpp)
  7. ## add libefg
  8. add_library(efg SHARED test_efg.cpp)
  9. target_link_libraries(efg abc)
  10. ## add main
  11. add_executable(${name} main.cpp)
  12. target_link_libraries(${name} efg abc)
复制代码
3. 结论

通过上述可以看到,中间的so(libefg)被main引用,main并不直接引用libabc的,所以中间编译的so也要加入相应的依赖,即使它能正常编译通过,实际是它找不到libabc的符号。



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大连全瓷种植牙齿制作中心

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表