undefined reference 问题各种情况分析

扒自网友文章

 

关于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 

    再编译会发现,问题已经成功解决。

转载于:https://www.cnblogs.com/azbane/p/9903104.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366785.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring交易可见性

在初始化应用程序上下文时,Spring遇到带有Transactional标记的类时会创建代理。 Transactional可以应用于类级别或方法级别。 在类级别应用它意味着该类中定义的所有公共方法都是事务性的。 Spring创建的代理类型,即Jdk代理或CGLIB代理,取决于…

Axios 作弊表(Cheat Sheet)

英文原文链接 GET 请求 // Make a request for a user with a given ID axios.get(/user?ID12345).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});// Optionally the request above could also be done as axios.get(…

loadrunner post请求

注意:loadrunner参数中的引号,需要自己加"\" post 请求,分为header 和body两个部分处理 header部分比较容易处理,使用函数实现,如web_add_header("pid","1")即可,具体参数可…

2018-2019-1 20165203 《信息安全系统设计基础》第六周学习总结

2018-2019-1 20165203 《信息安全系统设计基础》第六周学习总结 教材学习内容总结 重要知识点 I/O:在主存和外部设备(例如磁盘存储器、终端和网络)之间复制数据的过程。输入操作:从I/O设备复制数据到主存。输出操作:从…

linux 使用VI命令怎么删除输入内容,linux系统vi编辑器常用命令及使用方法。

在linux系统中编辑文档我们常用到vi编辑器。vi编辑器,通常称之为vi,是一种广泛存在于各种UNIX和Linux系统中的文本编辑程序。它的功能十分强大,但是命令繁多,不容易掌握,它可以执行输出、删除、查找、替换、块操作等众多文本操作&…

Spring安全–幕后

安全任务(例如,用户身份验证和用户查看应用程序资源的授权)通常由应用程序服务器处理。 可以将这些任务委托给Spring安全性流程,以减轻应用程序服务器处理这些任务的负担。 Spring安全性基本上通过实现标准javax.servlet.Filter来…

在react中使用svg的各种骚姿势

开头先抛个可供参考的项目ts-react-webpack4, 或脚手架steamer-react-ts 优势 SVG可被非常多的工具读取和修改(比如vscode)不失真, 放大缩小图像都很清晰SVG文件是纯粹的XML, 也是一种DOM结构使用方便, 设计软件可以直接导出 兼容性 上一张兼容性图表, 或到caniuse.com查看 …

chrome 浏览器的插件权限有多大?

转自:https://segmentfault.com/q/1010000003777353 1)Chrome插件本身有机制控制,不会无限制的开放很多权限给你2)页面的DOM元素时可以操作的,Chrome插件是和宿主页面之间是共享DOM对象,但是不共享Javascri…

3.2自定义方法

方法是类的一种行为,方会使我们的代码容易修改,方便阅读,实现封装和重用。比如前面使用的很多.net定义好的类的方法,当然我们也可以自定义方法。 3.2.1定义方法 语法: 访问修饰符 返回类型 方法名(参数列表) &#xff…

linux live cd ubuntu,在Windows 7上体验Ubuntu Live CD

http://download.gna.org/grub4dos/grub4dos-0.4.4.zip把grldr.mbr,grldr放到C盘根目录.注意:以管理员身份运行cmd,进行以下操作.备份/Boot/BCD:bcdedit /export "D:\BCD.backup"用bcdedit编辑启动文件/Boot/BCD添加GRUB引导项:bcdedit /create /d "GRUB" …

[Electron]仿写一个课堂随机点名小项目

自从前几个月下了抖音,无聊闲暇时就打会打开抖音,因为打开它有种莫名其妙打开了全世界的感觉... 无意中看到这个小视频:随机点名 于是仿写了一个课堂点名小项目,算是对Electron的一个简单的认识,有时间再深入。 项目…

何时以及如何使用ThreadLocal

正如我们的读者可能已经猜到的那样,我每天都在处理内存泄漏。 最近,一种特殊类型的OutOfMemoryError消息开始引起我的注意-滥用ThreadLocals触发的问题变得越来越频繁。 在查看此类泄漏的原因时,我开始相信其中一半以上是由于开发人员导致的&…

linux redis安装使用,linux安装redis

Linux(CentOS)中Redis介绍、安装、使用【一篇就够】2018-05-13 13:36:16 sjmz30071360 阅读数 1590更多分类专栏: redis版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。一、介绍Redis is…

用three.js写一个简单的3D射门游戏

这个小游戏很简单,一共由3个部分构成。1个平面(球场),1个球体(足球)还有一个立方体(球门)。 上个图给你们感受一下简陋的画风(掘金最高上传5M图片,原来图片都…

100份Spring面试问答-最终名单(PDF下载)

上次更新时间:2019年2月11日 这是有关Spring框架的一些最重要问题的摘要,在面试或面试测试过程中可能会要求您回答这些问题! 您无需担心下一次面试的机会,因为Java Code Geeks在这里为您服务! 您可能会被问到的大多数…

3.1 unittest简介

3.1 unittest简介 前言 熟悉java的应该都清楚常见的单元测试框架Junit和TestNG。python里面也有单元测试框架-unittest,相当于是一个python版的junit。python里面的单元测试框架除了unittest,还有一个pytest框架,这个用的比较少,后面有空再继…

织梦其他模型使用联动类型地区联动

官方模型的联动类型只能模型是在【独立模型】或者官方默认的【分类信息】模型下使用,其他模型下使用无效,我们来让联动类型支持所有模型。 添加联动地区类型字段 内容模型管理 - 文章模型(或者其他模型) - 添加新字段 字段名称 和 数据类型 千万别搞错了…

linux修改组的选项名字为,Linux用户、组及权限管理浅析

一、用户和组1.用户系统用来认证(Authentication),授权(Authorization),审计(Autition)的帐号。通过登录用户来登录系统。操作系统通过登录不同的用户来调用相对应权限的进程或程序,也可以说,用户是能获取系统资源的权限集合。2.用…

如何在 vue-cli v3.0 中使用 SCSS/SASS

在项目中使用 SCSS/SASS 进行样式编写无疑会节省很多开发样式的时间。关于如何在 vue-cli v3.0 中使用 SCSS/SASS,这里提供三种方案。前提是在使用 vue-cli 生成项目时勾选了 CSS Pre-processors (CSS预处理器),否则无法在项目中直接使用。 方案一&…

使用IntelliJ IDEA进行热部署

最近,在PrimeFaces论坛PrimeFaces IDE Poll中进行了投票,以投票赞成用于开发PrimeFaces应用程序的最佳IDE。 最多人投票支持NetBeans。 NetBeans和Eclipse是免费的IDE。 我最喜欢的IDE IntelliJ IDEA Ultimate不是免费的,我认为这就是为什么在…