[转]undefined reference问题总结
转自http://ticktick.blog.51cto.com/823160/431329
最近在Linux下编程发现一个诡异的现象,就是在链接一个静态库的时候总是报错,类似下面这样的错误:
- (.text+0x13): undefined reference to `func'
关于undefined reference这样的问题,大家其实经常会遇到,在此,我以详细地示例给出常见错误的各种原因以及解决方法,希望对初学者有所帮助。
1. 链接时缺失了相关目标文件(.o)
测试代码如下:

然后编译。
- gcc -c test.c
- gcc –c main.c
得到两个 .o 文件,一个是 main.o,一个是 test.o ,然后我们链接 .o 得到可执行程序:
gcc -o main main.o
这时,你会发现,报错了:
- main.o: In function `main':
- main.c:(.text+0x7): undefined reference to `test'
- collect2: ld returned 1 exit status
这就是最典型的undefined reference错误,因为在链接时发现找不到某个函数的实现文件,本例中test.o文件中包含了test()函数的实现,所以如果按下面这种方式链接就没事了。
- gcc -o main main.o test.o
【扩展】:其实上面为了让大家更加清楚底层原因,我把编译链接分开了,下面这样编译也会报undefined reference错,其实底层原因与上面是一样的。
- gcc -o main main.c //缺少test()的实现文件
需要改成如下形式才能成功,将test()函数的实现文件一起编译。
- gcc -o main main.c test.c //ok,没问题了
2. 链接时缺少相关的库文件(.a/.so)
在此,只举个静态库的例子,假设源码如下。

先把test.c编译成静态库(.a)文件
- gcc -c test.c
- ar -rc test.a test.o
至此,我们得到了test.a文件。我们开始编译main.c
- gcc -c main.c
这时,则生成了main.o文件,然后我们再通过如下命令进行链接希望得到可执行程序。
- gcc -o main main.o
你会发现,编译器报错了:
- /tmp/ccCPA13l.o: In function `main':
- main.c:(.text+0x7): undefined reference to `test'
- collect2: ld returned 1 exit status
其根本原因也是找不到test()函数的实现文件,由于该test()函数的实现在test.a这个静态库中的,故在链接的时候需要在其后加入test.a这个库,链接命令修改为如下形式即可。
- gcc -o main main.o ./test.a //注:./ 是给出了test.a的路径
【扩展】:同样,为了把问题说清楚,上面我们把代码的编译链接分开了,如果希望一次性生成可执行程序,则可以对main.c和test.a执行如下命令。
- gcc -o main main.c ./test.a //同样,如果不加test.a也会报错
3. 链接的库文件中又使用了另一个库文件
这种问题比较隐蔽,也是我最近遇到的与网上大家讨论的不同的问题,举例说明如下,首先,还是看看测试代码。

从上图可以看出,main.c调用了test.c的函数,test.c中又调用了fun.c的函数。
首先,我们先对fun.c,test.c,main.c进行编译,生成 .o文件。
- gcc -c func.c
- gcc -c test.c
- gcc -c main.c
然后,将test.c和func.c各自打包成为静态库文件。
- ar –rc func.a func.o
- ar –rc test.a test.o
这时,我们准备将main.o链接为可执行程序,由于我们的main.c中包含了对test()的调用,因此,应该在链接时将test.a作为我们的库文件,链接命令如下。
- gcc -o main main.o test.a
这时,编译器仍然会报错,如下:
- test.a(test.o): In function `test':
- test.c:(.text+0x13): undefined reference to `func'
- collect2: ld returned 1 exit status
就是说,链接的时候,发现我们的test.a调用了func()函数,找不到对应的实现。由此我们发现,原来我们还需要将test.a所引用到的库文件也加进来才能成功链接,因此命令如下。
- gcc -o main main.o test.a func.a
ok,这样就可以成功得到最终的程序了。同样,如果我们的库或者程序中引用了第三方库(如pthread.a)则同样在链接的时候需要给出第三方库的路径和库文件,否则就会得到undefined reference的错误。
4 多个库文件链接顺序问题
这种问题也非常的隐蔽,不仔细研究你可能会感到非常地莫名其妙。我们依然回到第3小节所讨论的问题中,在最后,如果我们把链接的库的顺序换一下,看看会发生什么结果?
- gcc -o main main.o func.a test.a
我们会得到如下报错.
- test.a(test.o): In function `test':
- test.c:(.text+0x13): undefined reference to `func'
- collect2: ld returned 1 exit status
因此,我们需要注意,在链接命令中给出所依赖的库时,需要注意库之间的依赖顺序,依赖其他库的库一定要放到被依赖库的前面,这样才能真正避免undefined reference的错误,完成编译链接。
5. 在c++代码中链接c语言的库
如果你的库文件由c代码生成的,则在c++代码中链接库中的函数时,也会碰到undefined reference的问题。下面举例说明。
首先,编写c语言版库文件:

编译,打包为静态库:test.a
- gcc -c test.c
- ar -rc test.a test.o
至此,我们得到了test.a文件。下面我们开始编写c++文件main.cpp

然后编译main.cpp生成可执行程序:
- g++ -o main main.cpp test.a
会发现报错:
- /tmp/ccJjiCoS.o: In function `main':
- main.cpp:(.text+0x7): undefined reference to `test()'
- collect2: ld returned 1 exit status
原因就是main.cpp为c++代码,调用了c语言库的函数,因此链接的时候找不到,解决方法:即在main.cpp中,把与c语言库test.a相关的头文件包含添加一个extern "C"的声明即可。例如,修改后的main.cpp如下:

- g++ -o main main.cpp test.a
再编译会发现,问题已经成功解决。
6. 总 结
当然,上面几种是我目前发现的比较常见的undefined reference错误的原因和解决方法,可能也有其他各种原因,欢迎大家来信lujun.hust@gmail.com交流,对本文档进行补充,方面新手们解决学习过程中遇到的各种问题。
[转]undefined reference问题总结的更多相关文章
- (转) Qt 出现“undefined reference to `vtable for”原因总结
由于Qt本身实现的机制所限,我们在使用Qt制作某些软件程序的时候,会遇到各种各样这样那样的问题,而且很多是很难,或者根本找不到原因的,即使解决了问题,如果有人问你为什么,你只能回答--不知道. 今天我 ...
- undefined reference to `__android_log_print'
使用android studio 编写NDK代码时出现错误:undefined reference to `__android_log_print' 解决办法: eclipse andro ...
- CentOS 6.5 编译 PHP-7 报错:undefined reference to `libiconv_open 无法编译 PHP libiconv
./configure --with-mysql=/backup/mysql --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zli ...
- Qt - 错误总结 - 在自定义类头文件中添加Q_OBJECT 编译时报错(undefined reference to ‘vtable for xxThread)
错误提示:在添加的QThread子类头文件添加Q_OBJECT时,编译程序,出现"undefined reference to 'vtable for xxThread'"错误提示 ...
- Qt经典出错信息之undefined reference to `vtable for classname
原文链接:Qt经典出错信息之undefined reference to `vtable for classname 这个出错信息太常见了,用过Qt两个月以上的朋友基本上都能自己解决了,因为太经典了, ...
- 解决undefined reference to `__poll_chk@GLIBC_2.16' 错误
出现这个错误,是系统的glibc版本太低了,需要更新 到http://ftp.gnu.org/gnu/glibc/下载新版本的glibc,也不用太高,我选择glibc-2.20.tar.gz 解压 ...
- ubuntu系统下,gsl 库链接问题 -undefined reference to `cblas_xxx`
今天在ubuntu系统下进行程序调试的时候出现以下错误信息: [ %] Linking CXX executable ../test_coco /usr/local/lib/libgsl.so: un ...
- Android APP使用NDK编译后的ffmpeg库出现undefined reference to 'posix_memalign'错误
在android程序中使用NDK编译后的ffmpeg库的时候出现了如下错误: jni/libs/libavutil.a(mem.o): in function av_malloc:libavutil/ ...
- undefined reference to `Spreadsheet::staticMetaObject'
<C++ GUI Qt 4 编程>学习 一.遇到的问题 在学完第4章后,Spreasheet程序也已经写好了.在用 FindDialog 搜索时发现没有效果. 二.解决过程 调试跟踪代码, ...
- undefined reference to `dlopen'
g++ -O0 -g3 -I. -Ithird/json -Ithird/core/include -Ithird/vite/include -Ithird/openfst-1.2.10/src/in ...
随机推荐
- laravel, Composer和autoloading
http://www.php-fig.org/psr/psr-4/ http://www.php-fig.org/psr/psr-0/ http://alanstorm.com/laravel_com ...
- 《自己动手写操作系统》pmtest2笔记
;DispReturn模拟一个回车的显示,(让下一个要显示的字符在下一行的开头处显示),其中edi始终指向要显示的下一个字符的位置.; ------------------------------ ...
- hdu 4614 pieces 状态DP
题意:给你一个长度小于等于16的字符串,每次可以删除一个回文传,问你最少删除干净的字数. 状态+dp dp[i] = min(dp[i],dp[j]+dp[j^i]);(j是i的字串): 连接:htt ...
- 02.C语言关于指针的学习笔记
指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址. 要搞清一个指针需要搞清指针的四方面的内容: 指针的类型,指针所指向的 类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内 ...
- Java 动态写轮眼 SharinganJPanel (整理)
/** * Java 动态写轮眼 SharingganJPanel (整理) * * 2016-1-2 深圳 南山平山村 曾剑锋 * 设计声明: * 1.虽然岸本是日本人,而我个人作为其模仿者,依 ...
- 20160129.CCPP体系详解(0008天)
程序片段(01):函数.c+call.c+测试.cpp 内容概要:函数 ///函数.c #include <stdio.h> #include <stdlib.h> //01. ...
- 一起学CUDA(零)
1.Nvidia为什么引入CUDA最近实验室已经有不少豪在入手本本了,因为学霸居多,所以大家一般都会说对显卡要求不高,不玩大型游戏,只是CPU不能差,Intel I7.3G的主频…… 其 实现在CPU ...
- greensock的tween源码阅读笔记
对于一个处于gc状态的tween,如果这个gc状态是由kill触发的,那么直接从masterList删除否则的话,被tweenlite的垃圾回收删除! 对于一个不是立即启动的tween,它被添加到ti ...
- html中的特殊符号
html中的特殊符号 符号 说明 编码 符号 说明 编码 符号 说明 编码 " 双引号 " × 乘号 × ← 向左箭头 ← & AND符号 & ÷ 除号 ÷ ...
- postgresql编译安装与调试(二)
接前文postgresql编译安装与调试(一),继续说说postgresql的编译安装与调试. 上一篇已经详细说明了如何在Linux系统上编译安装postgresql,这次我们在此基础上简单讲讲如何在 ...