undefined reference to xxx 问题总结

38 篇文章 1 订阅
25 篇文章 0 订阅

undefined reference to xxx 问题总结

GCC编译过程

  1. 预处理Pre-Processing;宏展开等,可以生成.i文件
  2. 编译Compiling(狭义的编译);进行语法分析,转换成汇编语言,生成.s文件
  3. 汇编Assembling;把汇编语言代码转换成目标代码,生成.o文件
  4. 连接Linking;连接器ld将as创建的目标文件转换为可执行文件,生成a.out文件

代码的基本语法与格式错误一般是在前几个阶段被发现的,
在最后一步即连接时才会报错 undefined reference to,即找不到符号的定义;

找不到符号定义的几种情况

链接时确实没有指定包含符号定义的相关文件;

  • 链接时没有指定包含符号定义的源文件(.c,.cpp);
  • 链接时没有指定包含符号定义源文件生成的目标文件(.o);
  • 链接时没有指定包含符号定义的库文件(.so,.a);

链接选项的顺序导致

越基础的库的连接选项越要靠后面;
如果 libB.so 又依赖于 libA.so, 则连接选项应该是 -lB, -lA

函数符号修饰导致

  • 函数定义和声明不一致,包括参数类型、个数及返回值,甚至其他修饰如const等;
  • C和C++混合编程,在应用C语言的库的时候,就要加上extern "C",告诉C++编译器按照C语言的符号修饰规则去找这些符号;

由于C++有符号修饰(Name Decoration)或符号改编(Name Mangling)的机制;导致编译生成的符号表和代码中定义的会有不同;
nm -C可以查看符号修饰之前的名字;

  • 编译器版本或者编译器选项不一致,编译库与链接库所使用的版本或选项不一致导致。

编译选项隐藏了接口

在编译库时如果使用了 -fvisibility=hidden 选项将导致其定义的接口对外不可见,通过nm命令导出符号表可以看到其类型不是T;
可以使用 -fvisibility=default 选项来编译动态库,恢复其默认的可见属性。
也可以在接口声明前加上__attribute__ ((visibility ("default")))显示声明接口可见。
可以定义成宏定义便于使用,示例如下

#define PUBLIC_API __attribute__ ((visibility ("default")))
#define LOCAL_API  __attribute__ ((visibility ("hidden")))

PUBLIC_API void public_api();
LOCAL_API void local_api();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值