由于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 ...
随机推荐
- CRF,没完全看懂
这篇文章,感觉讲的还比较浅显易懂: http://www.sohu.com/a/207085690_206784
- UVA 10790 (13.08.06)
How Many Points of Intersection? We have two rows. There are a dots on the toprow andb dots on the ...
- mysql的正则表达式
所谓正在表达式,就是通过模式去匹配一类字符串.MySQL支持的模式字符如下表所示: MySQL支持的模式字符 模式字符 含义 ^ 匹配字符串的开始部分 $ 匹配字符串的结束部分 . 匹配字符串中的任意 ...
- mysql 下 计算 两点 经纬度 之间的距离
公式如下,单位米: 第一点经纬度:lng1 lat1 第二点经纬度:lng2 lat2 round(6378.138*2*asin(sqrt(pow(sin( (lat1*pi()/180-lat2* ...
- FrameWork数据权限浅析4之基于多维度配置表实现行级数据安全
日子过得好苦逼,我过的很好,只是缺少¥.时间在变,而问题始终未变,你解不解决它都在那里一动不动.不知不觉已经发现手机的中央,电脑的右下角已经出现了201411的字样,突然从桌子上爬起来,差点忘记了自己 ...
- const 与过载
1.方法包括方法名,返回类型,形参表,修饰符. 2.对于一个方法,const可以出现的地方有返回类型,形参表,和方法后(const成员方法). 3.返回类型的常量性(是否为const)不同,不能构成过 ...
- Grunt的配置及使用(压缩合并js/css)
Grunt的配置及使用(压缩合并js/css) 安装 前提是你已经安装了nodejs和npm. 你能够在 nodejs.org 下载安装包安装.也能够通过包管理器(比方在 Mac 上用 homebre ...
- 初次使用IntelliJ IDEA
一.认识IDEA IDEA 全称IntelliJ IDEA,是java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持 ...
- 将图片转成base64字符串并在JSP页面显示的Java代码
*本事例主要讲了如下几点: * 1:将图片转换为BASE64加密字符串. * 2:将图片流转换为BASE64加密字符串. * 3:将BASE64加密字符串转换为图片. * 4:在jsp文件中以引 ...
- linux 打包和压缩文件
打包成tar文件 tar -cf mydir.tar mydir/ 打包tar压缩成gz tar -czf mydir.tar.gz mydir/ 解压mydirtar文件 tar -xvf mydi ...