由于link顺序错误导致的undefined reference
其实我之前就遇到过这个问题,也强调过,GNU-G++在link阶段是依赖输入的.o或者.a文件的顺序的。如果顺序错误会导致undefined reference错误
见这篇随笔:http://www.cnblogs.com/qrlozte/p/4137704.html
刚才我遇到的问题是什么呢?
代码demo.cpp:其中ZJ::open_max在util.h中声明,在$(PATH_ONE)/libutil.a中;err_sys在apue.h中声明,在$(PATH_TWO)/libapue.a中,这里我用makefile里的$(PATH_XXX)来表示路径的宏值
#include "apue.h"
#include "util.h" #include <iostream> int main(void)
{
const long opmax = ZJ::open_max();
std::cout << "opmax = " << opmax << std::endl;
err_sys("test err_sys");
return ;
}
编译链接成功,可运行。
其中链接命令为:
g++ -L$(PATH_ONE) -L$(PATH_TWO) -o bin/test_exe obj/demo.o -lapue -lutil
但是,如果把err_sys那一行代码删掉,再把#include "apue.h"删掉,makefile内容不变,就会报错:
$(PATH_ONE)/libutil.a(util.o): In function `ZJ::open_max()': util.cpp:(.text+0x56): undefined reference to `err_sys(char const*, ...)'
这里,我知道的是:ZJ::open_max中有对err_sys的调用,我不明白的是:如果确实有undefined reference错误,我没删那两行的时候就该报错了吧?我又没改makefile,这是什么情况?
后来经过几番折腾,终于发现这个不起眼的错误,就是在makefile里面:
g++ -L$(PATH_ONE) -L$(PATH_TWO) -o bin/test_exe obj/demo.o -lapue -lutil
正确的应该是:
g++ -L$(PATH_ONE) -L$(PATH_TWO) -o bin/test_exe obj/demo.o -lutil -lapue
为什么?
因为$(PATH_ONE)/libutil.a里面主要包含2个函数,ZJ::open_max和ZJ::path_max,这二者都依赖于$(PATH_TWO)/libapue.a中的err_sys
对于-lapue -lutil的情况,在链接的时候,linker先看到-lapue,在demo.o中也看到了对err_sys的调用,那么linker就知道在$(PATH_TWO)/libapue.a中能找到的err_sys的入口,同理,然后linker也能知道应该去$(PATH_ONE)/libutil.a中找ZJ::open_max的入口
但是,如果你删除了demo.cpp中对err_sys的声明和调用,那么linker就无法直接知道err_sys可以在$(PATH_TWO)/libapue.a中能找到,因此linker就开始顺序查找-lapue -lutil
首先linker开始检查demo.o中的函数调用,在main函数的第一行找到了对ZJ::open_max的调用,显然,此时linker依次查看-lapue(没有,因此跳过),-lutil(找到),因此linker就去$(PATH_ONE)/libutil.a中去找到ZJ::open_max的入口,然后在ZJ::open_max中找到了对err_sys的调用,但是,此时因为-lapue已经被linker跳过了,所以linker只会继续在-lutil中查找(当然找不到),然后再看-lutil后面还有没有-l参数(没有了),因此报错undefined reference to err_sys(当然,g++ linker的实现我不知道,我这里是纯属推测)不会再回头去看-lapue中能不能找到err_sys(而Microsoft的CL.EXE就不存在这个问题)。
对于-lutil -lapue的情况,上述的问题就不存在了,因为linker发现-lutil找不到err_sys,就会继续往下找,从而在-lapue中找到err_sys
废话这么多,总结:用GNU-GCC/G++的时候,链接顺序一定不要搞错!
由于link顺序错误导致的undefined reference的更多相关文章
- gcc参数-l传递顺序错误导致`undefined reference'的一点小结
刚才编译一个pthread的单文件程序, 使用的命令行是: gcc -o thread1 -lpthread thread1.c 结果报错: $ gcc -o thread1 -lpthread th ...
- qt程序运行时的错误error:undefined reference to `_imp___ZN10QTcpSocketD1Ev'
出现的错误: undefined reference to `_imp___ZN10QTcpSocketD1Ev' undefined reference to `_imp___ZN10QTcpSoc ...
- [转载]解决linux 下多线程错误 undefined reference to `sem_init'
转自:https://blog.csdn.net/yzycqu/article/details/7396498?utm_source=copy 解决linux 下多线程错误 undefined ref ...
- Android NDK编译之undefined reference to 'JNI_CreateJavaVM'
利用Android NDK编译动态库,在C文件中调用了两个JNI函数:JNI_GetDefaultJavaVMInitArgs和JNI_CreateJavaVM.编译的时候始终报以下错误: XXX: ...
- undefined reference to `__sync_bool_compare_and_swap_4
然后开始glibc的编译工作. 你必须设定march这个参数才行,要不然会出现“undefined reference to `__sync_bool_compare_and_swap_4′.”这个错 ...
- error: undefined reference to 'av_register_all()'
cygwin下ndk编译工程中使用ffmpeg时出现的错误:“error: undefined reference to 'av_register_all()'” 使用ffmpeg的源文件是 *.c ...
- 47: error: undefined reference to `QWebView::QWebView(QWidget*)'
QT 5.6版本 用Qt界面设计器打开界面文件,在界面上托入QWebView控件,这时运行会出现错误,错误如下: ......... undefined reference to `QWebView ...
- nios ii 13 主程序的函数可以用Open Declaration 查看,但是编译的时候却说 undefined reference to 。。。这是为什么?
在做12864 ip 核试验时,写了三个文件第一个是时序文件QC12864.v第二个是QC12864.H这个文件主要包括声明和宏定义,第三个文件是QC12864.c这个文件包含函数的定义.详细的请看 ...
- Linux下运行《UNIX环境高级编程》undefined reference to `err_quit 编译出错的处理方法
错误信息: : undefined reference to `err_quit': undefined reference to `err_sys' 解决方法: 因为err_quit跟err_sys ...
随机推荐
- Informatica 常用组件Source Qualifier之四 SQL Query
源限定符转换提供 SQL 查询选项以覆盖默认的查询.您可以输入您的源数据库支持的 SQL 语句.输入查询之前,请连接您要在映射中使用的所有输入和输出端口. 编辑 SQL 查询时,您可以生成并编辑默认查 ...
- 挑战黑客极限:Pwn2Own 2015成史上“最难”黑客大赛
Pwn2Own是全球最著名.奖金最丰厚的黑客大赛,由美国五角大楼入侵防护系统供应商TippingPoint赞助.近日Pwn2Own 2015公布全新的比赛规则,本届赛事难度超高.史无前例,包括VUPE ...
- 排查VMWare虚拟机的性能问题
Troubleshooting ESX/ESXi virtual machine performance issues (2001003) http://kb.vmware.com/selfservi ...
- input type=file文件选择表单元素二三事
一.原生input上传与表单form元素 如果想使用浏览器原生特性实现文件上传(如图片)效果,父级的form元素有个东西不能丢,就是: enctype="multipart/form-dat ...
- Java最大的优势真的在于跨平台吗?
下面讨论仅仅针对PC端和移动端. 曾经是,但如今已经不是了. 有跨平台需求的仅仅是client应用.而不是服务端.比如桌面应用,你的客户可能是Windows用户.也可能是Linux用户,这时候假设不想 ...
- ArcGIS Add-In调试无法重新生成
在调试ArcGIS Add-In时,出现错误:无法注册程序集"……\Projects\ArcGISAddIn\ArcGISAddIn\bin\Debug\ArcGISAddIn.dll&qu ...
- http协议中content-length 以及chunked编码分析
转载请注明出处 http://blog.csdn.net/yankai0219/article/details/8269922 0.序 1.http/1.1协议中与chunked编码的相关字段 1)E ...
- 判断IE浏览器版本的精简脚本
IE浏览器不管是什么版本,总是跟Web标准有些不太兼容.对于代码工作者来说,自然是苦不堪言,为了考虑IE的兼容问题,不管是写 CSS 还是 JS,往往都要对 IE 特别对待,这就少不了做些判断.本文不 ...
- Linux回环接口(loop-back/loopback)
回环接口(loop-back/loopback) Moakap整理 Loopback接口是一个虚拟网络接口,在不同的领域,其含义也大不一样. 1. TCP/IP协议栈中的loopback接口 在TCP ...
- SVN 快速入门!
输入账户密码即可!