undefined reference to 问题汇总及解决方法 ----- 还有一种问题没有解决(可能是顺序问题)

  1、链接时缺失了相关的目标文件

  2、链接时缺少了相关的库文件

  3、链接的库文件中有使用了另一个库文件

  4、多个库文件链接顺序问题

  5、定义与实现不一致

  6、在c++代码中链接C语言的库

转载地址: https://segmentfault.com/a/1190000006049907?utm_source=tuicool&utm_medium=referral

在实际编译代码的过程中,我们经常会遇到"undefined reference to"的问题,简单的可以轻易地解决,但有些却隐藏得很深,需要花费大量的时间去排查。工作中遇到了各色各样类似的问题,按照以下几种可能出现的状况去排查,可有利于理清头绪,从而迅速解决问题。

链接时缺失了相关目标文件

首先编写如下的测试代码:

// test.h

#ifndef __TEST_H__
#define __TEST_H__

void test();

#endif

// test.c

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

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

// main.c

#include "test.h"

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

    return 0;
}

通过以下的命令,我们将会得到两个.o文件。

$ gcc -c test.c
$ gcc –c main.c 

随后,我们将main.o这个文件,编译成可执行文件。

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

编译时报错了,这是最典型的undefined reference错误,因为在链接时发现找不到某个函数的实现文件。如果按下面这种方式链接就正确了。

$ gcc -o main main.o test.o

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

$ 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编译成可执行文件。

$ gcc -o main main.c test.a
ld: warning: ignoring file test.a, file was built for archive which is not the architecture being linked (x86_64): test.a
Undefined symbols for architecture x86_64:
  "_test", referenced from:
      _main in main-f27cf1.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()这个函数的声明和定义不一致导致,将两者更改成一样即可通过编译。

c++代码中链接c语言的库

代码同示例一的代码一样,只是把main.c更改成了main.cpp。编译test.c,并打包为静态库。

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

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

$ g++ -o main main.cpp test.a
Undefined symbols for architecture x86_64:
  "test()", referenced from:
      _main in main-7d7fde.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

原因就是main.cppc++代码,调用了c语言库的函数,因此链接的时候找不到,解决方法是在相关文件添加一个extern "C"的声明即可,例如修改test.h文件。

// test.h

#ifndef __TEST_H__
#define __TEST_H__

#ifdef __cplusplus
extern "C" {
#endif

void test();

#ifdef __cplusplus
}
#endif

#endif

原文地址:https://www.cnblogs.com/coolYuan/p/8624253.html

时间: 2024-10-12 23:08:26

undefined reference to 问题汇总及解决方法 ----- 还有一种问题没有解决(可能是顺序问题)的相关文章

***在Linux环境下mysql的root密码忘记解决方法(三种)-推荐第三种

MySQL密码的恢复方法之一 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录和修改MySQL的信息.可以采用将MySQL对外的端口封闭,并且停止Apache以及所有的用户进程的方法实现服务器的准安全状态.最安全的状态是到服务器的Console上面操作,并且拔掉网线. 2.修改MySQL的登录设置: ? 1 # vi /etc/my.cnf 在[

&quot;undefined reference to&quot; 多种可能出现的问题解决方法

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

ie6,ie7,ie8 css bug汇总以及兼容解决方法

1:li边距“无故”增加 任何事情都是有原因的,li边距也不例外. 先描述一下具体状况:有些时候li边距会突然增 加很多,值也不固定(只在IE6/IE7有这种现象),让人摸不着头脑,仔细“研究”发现是由于其低级元素ul的padding引 起,padding的上下值对li有影响,左右无影 响.所以只好笨手笨脚地把padding去掉,换成margin.这是能解决问题,但往往不是我们想要的结果,或许 还会引起其他不必要的怪现象. 解决这个问题的方法,其实很简单,既然是有ul引 起的,就设置ul的显示形

apace访问403错误的解决方法汇总

作为一个努力学习的实习生,遇到问题还是靠记录才能更好的学习. 首先附上故障图 翻译过来就是啥呢? 于是天真的我去百度了一下大神们的解决方法,目录没权限嘛,来个777就完事了.一开始还觉得挺合乎情理的,于是就上了(论学习安全的重要性) 结果还是老样子,后来又继续找答案,有人说不允许空目录(不允许列出目录列表),于是就检查一下,发现的确没有任何文件在Web根目录,于是 echo "hello" > /var/www/html/index.html 然后再重启apace(httpd)服

DLNA之 Error, can&#39;t findlibavformat ! 解决方法

DLNA库版本为libdlna-0.2.4 执行./configure出错: ------------------------------ Error, can't findlibavformat ! -------------------------------------------- 查看config.log文件: ---------------------------------------------------------- - /usr/local/lib/libavformat.

dedecms后台管理忘记密码了的解决方法

dedecms后台管理密码忘记了,该怎么办呢?这里给出2种解决方法: 第一种,使用phpmyadmin,前提是你有phpmyadmin这个工具,如果是空间,可以咨询空间商或者空间管理面板获取,如果是VPS或者服务器就需要自己架设了. 打开phpmyadmin,找到管理员表.一般是dede_admin,找到管理员的哪行.修改PWD的值.(dedecms的密码是MD5除去前五和后七位置数值,剩下的20位字符串就是密码) 替换PWD值为f297a57a5a743894a0e4这个密码就是 admin,

Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错,

Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错, 这里总结一些可能的原因和解决方案,给需要的朋友: 说道undefined reference error,先提一下Linux gcc链接规则: 链接的时候查找顺序是: -L 指定的路径, 从左到右依次查找 由 环境变量 LIBRARY_PATH 指定的路径,使用":"分割从左到右依次查找 /etc/ld.so.conf 指定的路径顺序 /lib 和 /usr/lib (64位下是/lib

MYSQL安装时解决要输入current root password的解决方法

在装MYSQL的时候发现要输入current root password不记得以前在电脑里装过(你的系统曾经装过MYSQL在重装就会要求输入原来设定的密码,如果是第一次安装就不会出现),在网上苦苦搜寻解决方法. 终归结出以下解决方法: 1.清除MYSQL的安装目录,默认是C:\Program Files 2.清除MYSQL数据存放目录,一般在C:\Documents and Settings\All Users.windows\Application Data目录下 (需要注意的时Applica

Linux使用退格键时出现^H解决方法

以前在linux下执行脚本不注意输错内容需要删除时总是出现^H ,以前不知道真相的我没办法只有再重头运行一次脚本,后来发现其实时有解决办法的,所以记录一下. ^H不是H键的意思,是backspace.主要是当你的终端backspace有问题的时候才需要设置. 解决方法有两种:1.要使用回删键(backspace)时,同时按住ctrl键2.设定环境变量在脚本的开头或结尾 参数 stty erase ^H stty erase ^?在bash下:$ stty erase ^?或者把 stty era