编译链接“ undefined reference to ”

最近在移植一个项目,从windows移植到Linux,在解决掉编译前期问题后,在链接的时候碰到了各种的“ undefined reference to ”问题。

检查所依赖的.h文件是否 #include <>

首先检查所依赖的.h文件是否 #include“xxx.h”

链接时缺少了相关的目标文件(.o)或者库文件(.so)

造成这种情况的原因比较多:

忘记指定目标文件(.o);

忘记指定链接库(-L /xxx/yyy/  -lA);

遗漏指定链接库(B动态库依赖A动态库,链接忘记指定A动态库 -lA)

fun.h

#ifndef __FUN_H__
#define __FUN_H__

int fun();

#endif

fun.cpp

#include "fun.h"
int fun()
{
	return 0;
}

fun1.h

#ifndef __FUN1_H__
#define __FUN1_H__

int fun1();

#endif

fun1.cpp

#include "fun.h"

int fun1()
{
	return fun();
}

缺少链接库

root@localhost:~/test# g++ -fpic -shared fun.cpp -o libfun.so
root@localhost:~/test# g++ -fpic -shared fun1.cpp -o libfun1.so
root@localhost:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun1
.//libfun1.so: undefined reference to `fun()'
collect2: error: ld returned 1 exit status

正确的编译

root@localhost:~/test# g++ -fpic -shared fun.cpp -o libfun.so
root@localhost:~/test# g++ -fpic -shared fun1.cpp -o libfun1.so
root@localhost:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun1 -lfun
root@localhost:~/test#

动态库依赖顺序

上边的例子libfun1.so依赖libfun.so ,编译时错误的顺序会导致“ undefined reference to ”;越基础的库越要放到后边。

 

错误的顺序

root@localhost:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun -lfun1
.//libfun1.so: undefined reference to `fun()'
collect2: error: ld returned 1 exit status

正确的顺序

root@localhost:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun1 -lfun

头文件有函数声明,但cpp文件没有实现

移植项目的时候,有些基础库虽然头文件有函数声明,但动态库没有实现。

稍微修改一下fun1.h  和main.cpp

fun1.h

#ifndef __FUN1_H__
#define __FUN1_H__

int fun1();
int fun2();

#endif

main.cpp

#include <fun1.h>
int main()
{
	fun2();
}

编译

root@localhost:~/test# g++ -fpic -shared fun.cpp -o libfun.so
root@localhost:~/test# g++ -fpic -shared fun1.cpp -o libfun1.so
root@localhost:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun1 -lfun
/tmp/cc23ESs7.o: In function `main':
main.cpp:(.text+0x5): undefined reference to `fun2()'
collect2: error: ld returned 1 exit status

用别人的库时,往往没有源文件,这时候就要利用nm命令或者objdump命令查看.so是否包含报错的符号

root@localhost:~/test# nm libfun.so | grep fun
00000000000007f4 t _GLOBAL__sub_I_fun.cpp
00000000000007a0 T _Z3funv
root@localhost:~/test# nm libfun.so | grep fun | c++filt 
00000000000007f4 t _GLOBAL__sub_I_fun.cpp
00000000000007a0 T fun()

这里会发现并没有fun2()函数实现,只有fun()的定义。

gcc 和 g++的编译  extern “C”{}

c++支持函数重载,编译器在编译c++代码对函数名的修饰和 编译C代码对函数名的修饰是不一样的。

在使用纯c编译的动态库引用头文件时要加上:

extern "C" {
#include "func.h"
}

 

在自己编写动态库时,也要注意头文件和cpp文件的 extern "C" {} 所包含的内容要对应起来。

fun1.h

#ifndef __FUN1_H__
#define __FUN1_H__

#ifdef __cplusplus
extern "C" {
#endif

int fun1();
int fun2();

#ifdef __cplusplus
}
#endif

#endif

fun1.cpp

#include "fun.h"
#ifdef __cplusplus
extern "C" {
#endif

int fun1()
{
	return fun();
}
#ifdef __cplusplus
}
#endif

int  fun2()
{
	return 0;
}

main.cpp

int main()
{
	fun2();
}

编译

root@localhost:~/test# g++ -fpic -shared fun.cpp -o libfun.so
root@localhost:~/test# g++ -fpic -shared fun1.cpp -o libfun1.so
root@localhost:~/test# g++ main.cpp -o main -L ./ -I ./ -lfun1 -lfun
/tmp/ccQNCmKt.o: In function `main':
main.cpp:(.text+0xa): undefined reference to `fun2'
collect2: error: ld returned 1 exit status

 

root@localhost:~/test# nm libfun1.so | grep fun
000000000000085f t _GLOBAL__sub_I_fun1.cpp
                 U _Z3funv
000000000000080b T _Z4fun2v
0000000000000800 T fun1

头文件中fun2()在extern “C”{}里,而实现不在extern "C" {}中, 链接时查找不到fun2,因为声明是C( fun2 ),而实现是C++(_Z4fun2v)

 

这样的问题只要注意C++用纯C编译的库时引用头文件用extern "C" {}包含;自己编写动态库时头文件和实现文件extern "C" {}包含的内容要对应。

 

 

 

 

参考:https://www.cnblogs.com/QQ-1615160629/p/6233866.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注