“undefined reference to“ 问题汇总及解决方法 ------非常非常好的一篇文章

当然,也可以按照如下的命令编译,这样就可以一步到位。

$ gcc -o main main.**c** test.**c**
链接时缺少相关的库文件

我们把第一个示例中的test.c编译成静态库。

$ gcc -c test.c  
$ ar -rc test.a test.o 

接着编译可执行文件,使用如下命令:

$ gcc -o main main.c 
Undefined symbols **for** architecture x86_64:
  "\_test", referenced from:
      _main **in** main-6ac26d.o
ld: symbol(s) not found **for** architecture x86_64
clang: error: linker command failed with **exit** code 1 (use -v to see invocation)

其根本原因也是找不到test()函数的实现文件,由于test()函数的实现在test.a这个静态库中,故在链接的时候需要在其后加入test.a这个库,链接命令修改为如下形式即可。

$ gcc -o main main.c test.a
链接的库文件中又使用了另一个库文件  (这个例子非常非常好, 我就是犯了这种错误!!!)

先更改一下第一个示例中使用到的代码,在test()中调用其它的函数,更改的代码如下所示。


`// func.h

**#ifndef \_\_FUNC\_H\_\_**
**#define \_\_FUNC\_H\_\_**

**void** **func**();

**#endif**

// func.c

**#include <stdio.h>**

**void** **func**()
{
 printf("call it\n");
}

// test.h

**#ifndef \_\_TEST\_H\_\_**
**#define \_\_TEST\_H\_\_**

**void** **test**();

**#endif**

// test.c

**#include <string.h>**
**#include <stdio.h>**

**#include "func.h"**



**void** **test**()
{
 printf("just test it\n");

 func();
}

// main.c

**#include "test.h"**

**int** **main**(**int** argc, **char** **argv)
{
 test();

 **return** 0;
}`

我们先对fun.ctest.c进行编译,生成.o文件。

$ gcc -**c** func.**c**  
$ gcc -**c** test.**c**

然后,将test.cfunc.c各自打包成为静态库文件。

$ ar –rc func.a func.o  
$ ar –rc test.a test.o 

这时将main.c编译为可执行程序,由于main.c中包含了对test()的调用,因此,应该在链接时将test.a作为我们的库文件,链接命令如下。

$ gcc -o main main.c test.a
Undefined symbols **for** architecture x86_64:
  "\_func", referenced from:
      _test **in** test.a(test.o)
ld: symbol(s) not found **for** architecture x86_64
clang: error: linker command failed with **exit** code 1 (use -v to see invocation)

就是说,链接的时候发现test.a调用了func()函数,找不到对应的实现,我们还需要将test.a所引用到的库文件也加进来才能成功链接,因此命令如下。

$ gcc -o main main.c test.a func.a

同样,如果我们的库或者程序中引用了第三方库(如pthread.a)则在链接的时候需要给出第三方库的路径和库文件,否则就会得到undefined reference的错误。

多个库文件链接顺序问题

这种问题非常隐蔽,不仔细研究,可能会感到非常地莫名其妙。以第三个示例为测试代码,把链接库的顺序换一下,如下所示:

$ gcc -o main main.c 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的错误,完成编译链接。

备注:在MAC上可以正常编译通过。

定义与实现不一致

编写测试代码如下:


`// test.h

**#ifndef \_\_TEST\_H\_\_**
**#define \_\_TEST\_H\_\_**

**void** **test**(**unsigned** **int** c);

**#endif**

// test.c

**#include <string.h>**
**#include <stdio.h>**



**void** **test**(**int** c)
{
 printf("just test it\n");
}

// main.c

**#include "test.h"**

**int** **main**(**int** argc, **char** **argv)
{
 test(5);

 **return** 0;
}`

先将test.c编译成库文件。

$ gcc -c test.c 
$ ar -rc test.a test.o

main.c编译成可执行文件。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

$ gcc -c test.c 
$ ar -rc test.a test.o

main.c编译成可执行文件。

[外链图片转存中…(img-qH9A9YzE-1726115367932)]
[外链图片转存中…(img-8JiPOJUk-1726115367933)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值