前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解决make编译链接动态库错误:libxx.so: undefined reference to xx

解决make编译链接动态库错误:libxx.so: undefined reference to xx

作者头像
typecodes
发布2024-03-29 14:12:39
1280
发布2024-03-29 14:12:39
举报
文章被收录于专栏:typecodestypecodes

最近在写一个Makefile,调试时遇到了libsrcpbl.so: undefined reference to gcProgramName的问题。在这个Makefile脚本里面,终极目标是通过链接一个自定义的动态库libsrcpbl.so生成一个ELF目标文件。

由于链接生成libsrcpbl.so动态库的.o文件比较多,无法定位具体的错误程序文件和位置,所以折腾了较长时间。

1 场景再现

为了能快速定位出错的位置,自己写了一个很简单的测试程序test.c,该程序调用了libsrcpbl.so动态库中的一个自定义的公共头文件pbl_global.h

1 2 3 4 5 6 7 8 9 10 11 12 13

/** * @FileName tst.c * @Describe a simple test program to find out the reason of dynamic library undefined reference. * @Author vfhky 2015.08.12 https://typecodes.com/cseries/libraryundefinedref.html */ #include <stdio.h> #include "pbl_global.h" //为减少“干扰”,还可以去掉这个头文件引用 int main( int argc, char ** argv ) { printf( "exit\n" ); return 0; }

接着使用make命令编译链接生成目标ELF文件test,但是在ld链接自定义的动态库libsrcpbl.so的时候报错。为了减少干扰,还可以把pbl_global.h头文件引用去掉。也就是tst.c中是一个及其普通的程序,与libsrcpbl.so中的数据完全没关系,但是还是报出同样的错误:

代码语言:javascript
复制
[root@typecodes test]# make
gcc -std=c99 -D_GNU_SOURCE  -g -Wall  -I /root/gcc_test/tcp_msg/include/ -I /root/gcc_test/tcp_msg/include/CommAPI/ -I /root/gcc_test/tcp_msg/include/pbl/ -o /root/gcc_test/tcp_msg/src/test/tst.o -c tst.c
g++ -std=c99 -D_GNU_SOURCE   /root/gcc_test/tcp_msg/src/test/tst.o -L /root/gcc_test/tcp_msg/lib  -lsrcpbl -Xlinker "-("  -Xlinker "-)" -o /root/gcc_test/tcp_msg/bin/test
/root/gcc_test/tcp_msg/lib/libsrcpbl.so: undefined reference to `gcProgramName'
collect2: error: ld returned 1 exit status
make: *** [/root/gcc_test/tcp_msg/bin/test] Error 1
ld链接时报错:undefined reference
ld链接时报错:undefined reference
2 查找 libsrcpbl.so: undefined reference to gcProgramName 的原因

通过make显示的内容,基本判断Makefile文件是正确的。用nm libsrcpbl.so命令查看一下链接的动态库,结果如下:

代码语言:javascript
复制
##### 使用nm查看动态库
[root@typecodes test]# nm -A /root/gcc_test/tcp_msg/lib/libsrcpbl.so|grep gcProgramName
/root/gcc_test/tcp_msg/lib/libsrcpbl.so:                 U gcProgramName
[root@typecodes test]#
使用nm查看动态库中的符号
使用nm查看动态库中的符号

根据上图中的信息,结合前文《Unix系统中nm命令展示目标文件符号的方法》nm命令的man手册关于符号U的说明,推测可能原因:libsrcpbl.so动态库文件中存在gcProgramName符号(即变量),需要从test.o对象文件中链接进来,但是test.c程序中没有定义gcProgramName变量,所以报错了。

于是查看原工程中的头文件pbl_global.h,果然发现了gcProgramName是一个外部全局变量,其声明如下:

代码语言:javascript
复制
extern char gcProgramName[20 + 1];

接着发现生成这个libsrcpbl.so动态库的一个源程序中,通过引用头文件pbl_global.h,然后直接使用了这个外部全局变量gcProgramName,因此需要在tst.c对这个变量进行定义。

2 解决方法

找到原因后,解决就很简单了:只要在test.c程序中定义这个外部全局变量gcProgramName即可。

1 2 3 4 5 6 7 8 9 10 11

#include <stdio.h> //定义外部全局变量,解决libsrcpbl.so: undefined reference to gcProgramName的问题 char gcProgramName20 + 1 = {0x00}; int main( int argc, char ** argv ) { //在这里就可以随便赋值使用了 memcpy( gcProgramName, "TestPrg", strlen( "TestPrg" ) ); printf( "exit\n" ); return 0; }

最后重新make一下,链接生成ELF文件成功!

使用nm查看动态库中的符号
使用nm查看动态库中的符号
4 总结

在make编译链接某个动态库lxx.so时,如果报libxx.so: undefined reference to xx的话,很可能是由下面两种原因引起的。Unix/Linux系统中使用nmobjdumpreadelf命令可以辅助调试目标文件。

代码语言:javascript
复制
1、链接的动态库中存在只做了声明的自定义的函数/全局变量,但是在其它对象文件中没有实现定义;
2、链接生成的目标文件中引用了某动态库的自定义函数/全局变量,但是没有通过`-lXX`选项链接进来。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-08-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 场景再现
  • 2 查找 libsrcpbl.so: undefined reference to gcProgramName 的原因
    • 2 解决方法
      • 4 总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档