由于link顺序错误导致的undefined reference
2015-04-29 00:21
225 查看
其实我之前就遇到过这个问题,也强调过,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)来表示路径的宏值
编译链接成功,可运行。
其中链接命令为:
但是,如果把err_sys那一行代码删掉,再把#include "apue.h"删掉,makefile内容不变,就会报错:
这里,我知道的是:ZJ::open_max中有对err_sys的调用,我不明白的是:如果确实有undefined reference错误,我没删那两行的时候就该报错了吧?我又没改makefile,这是什么情况?
后来经过几番折腾,终于发现这个不起眼的错误,就是在makefile里面:
正确的应该是:
为什么?
因为$(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++的时候,链接顺序一定不要搞错!
见这篇随笔: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 0; }
编译链接成功,可运行。
其中链接命令为:
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 错误
- qt creator中Q_OBJECT导致出现undefined reference to vtable for 的错误
- 【GCC】参数顺序导致的“undefined reference”问题
- link错误 qt undefined reference to
- 库依赖错误导致main.c:(.text+0x7): undefined reference问题
- GCC版本不兼容导致的链接错误:undefined reference to `SomeFunction'
- Qt错误:类中使用Q_OBJECT宏导致undefined reference to vtable for "xxx::xxx"错误的原因和解决方法
- undefined reference to `clock_nanosleep' 错误
- 由于错误传入Marshal.GetTypedObjectForIUnknown参数导致的应用程序crash
- Oracle由于排序字段错误,导致分页数据错误,错误原因真的想不到!!!
- 错误提示:undefined reference to `pthread_create'
- 由于枚举类型导致的1 duplicate symbol for architecture x86_64错误
- C++编程错误 : undefined reference to `vtable for Student'
- 编译什么时候出现Undefined reference to 的错误
- 由于修改了Sps登录帐户在域中的密码,而导致的错误-Service Unavailable。
- 由于jar包版本不匹配导致整个项目出现莫名其妙的错误影响项目整体进程。
- Codeblocks 添加库(undefined reference 错误的处理)
- Ubuntu11.20 32位linux下编译cppunit报 libcppunit.so: undefined reference to `dlsym'错误问题
- jni中出现使用LOGD,出现undefined reference to '__android_log_print错误
- C++ link error : undefined reference to 'vtable for ...'