Linux——编译器gcc/g++、调试器gdb以及自动化构建工具makefilemake详解

编译器—gcc/g++、调试器—gdb以及自动化构建工具—makefile&&make

文章目录

  • 编译器—gcc/g++、调试器—gdb以及自动化构建工具—makefile&&make
  • 1. 编译器——gcc/g++
    • 1.1 生成可执行文件与修改默认可执行文件
    • 1.2 程序的翻译过程以及对应的gcc选项
      • 1.2.1 预处理 gcc -E
      • 1.2.2 编译 gcc -S
      • 1.2.3 汇编 gcc -c
      • 1.2.4 链接 gcc
  • 2. 调试器——gdb
    • 2.1 debug版本和release版本
    • 2.2 gdb常用功能及其选项
      • 2.2.1 查看代码
      • 2.2.2 开始/退出调试
      • 2.2.3 断点设置
      • 2.2.4 逐语句/逐过程
      • 2.2.5 断点跳跃
      • 2.2.6 查看变量
      • 2.2.7 查看函数调用堆栈
  • 3. 自动划构建工具——makekfile&&make
    • 3.1 makefile
    • 3.2 make
      • 3.2.1 工作原理
      • 3.2.2 文件的acm时间

本章思维导图:
在这里插入图片描述注:本章思维导图对应的 .xmind.png文件都已同步导入至 资源

1. 编译器——gcc/g++

安装命令

  • gcc:sudo yum install -y gcc
  • g++:sudo yum install -y gcc-c++
  • gcc只能编译C语言代码,g++既可以编译C语言代码也可以编译C++代码
  • 推荐用gcc编译C语言代码

注:gcc和g++的选项一致,下面的讲解都以gcc为例


1.1 生成可执行文件与修改默认可执行文件

我们可以直接用gcc编译器将一个.c文件直接编译成可执行文件

命令:

gcc filename

在这种情况下,会默认生成一个a.out可执行文件

在这里插入图片描述

如果我们想要指定生成的可执行文件的名字,可以加入-o选项

gcc -o newName filename

在这里插入图片描述

当然,如果想要对gcc编译器做更多的了解,上面的操作显然是不够的,我们需要结合程序的翻译过程来进行学习

1.2 程序的翻译过程以及对应的gcc选项

众所周知,程序的翻译分为了四个步骤:预处理、编译、汇编、链接。要学会只用Linux的编译器:gcc/g++,固然也需要理解这四个步骤

关于这四个步骤,博主已经在程序的翻译环境和运行环境做了较为详细的阐述,故下面只对这四个步骤做简单的讲解:

1.2.1 预处理 gcc -E

在这一过程,编译器会进行头文件展开、宏替换、条件编译等过程

对应的gcc命令为:

gcc -E -o file.i file

  • -E:即为预处理的gcc选项。表示预处理完后就停止
  • 预处理完后生成的文件后缀一般为.i

演示

在这里插入图片描述

可以看到,所谓的头文件展开实际上就是将头文件的内容拷贝至源文件中,预处理后得到的文件仍是C语言

1.2.2 编译 gcc -S

在这一过程,会对与处理过后的文件进行语法分析和词义分析,如果没有错误,就会生成以一个由汇编代码所写的文件

对应的gcc命令为:

gcc -S -o file.s file

  • -S:即为编译的gcc选项。表示编译完后就停止

  • 编译生成的文件的后缀名一般为.s

演示

在这里插入图片描述

1.2.3 汇编 gcc -c

在这一过程中,会将汇编代码转换为二进制代码,形成一个二进制文件

对应的gcc命令为:

gcc -c -o file.o file

  • -c:即为汇编的gcc选项。表示汇编完后就停止
  • 汇编生成的二进制文件我们称其为目标文件.obj,文件后缀可以为.o

演示

在这里插入图片描述

1.2.4 链接 gcc

会对目标文件进行动静态库链接,形成最终的可执行程序.exe

对应的gcc命令为:

gcc -o newName filename

  • 可以看到,用这条命令就可以直接生成一个可执行程序

演示:

在这里插入图片描述

以前写代码时大家可能会有一个疑惑:我明明没有声明和定义printf()、scanf()等库函数,为什么我可以正常使用呢

而之所以我们可以使用这些库函数,正是因为编译器有链接这一过程,这一过程将目标文件和库文件进行链接,从而让我们可以使用库中声明和定义好的函数

我们可以用命令:ldd file,查看一个文件依赖的库文件

函数库分为动态库和静态库两种

动态库

  • 动态库不包含在可执行程序中,而是在程序运行时由操作系统或者程序自行加载
  • 多个程序可以共享一个动态库,因此如果采用动态链接可以**减少程序所占用的
  • 使用动态链接的程序对库的依赖性较强,因此一旦库丢失,会使依赖这个库的程序都无法运行
  • gcc/g++编译默认进行的是动态链接

在这里插入图片描述

静态库

一般来说,需要自己对C语言和C++的静态库进行安装,执行下面两个命令即可:

sudo yum install -y glibc -static

sudo yum install -y libstdc++ -static

  • 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中的库
  • 静态库包含在可执行程序中,因此使用静态链接的程序对库的依赖性较弱,同类型平台都可以使用
  • 由于可执行程序包含了库文件的拷贝,因此使用静态链接的程序会占用较多的资源空间(内存、磁盘)
  • 如果要使gcc/g++进行静态链接,就要加入-static选项

在这里插入图片描述

2. 调试器——gdb

安装命令:

sudo yum install -y gdb

为了能够更好的理解,我们先来谈谈程序发布的两个版本——debug版本release版本

2.1 debug版本和release版本

在这里插入图片描述

首先我们要清楚:

  • Linux上的gcc和g++编译出来的可执行程序默认都是release版本的
  • release版本是不支持调试的,只有在debug版本下才能调试

为了在Linux上能够生成debug版本的可执行程序,我们需要在编译时加上选项-g

gcc -o newFile file -g

下面,我们再来谈谈为什么一个程序要有debugrelease两个版:

  • 在程序的开发阶段,程序难免会出现各种问题,而为了能够方便程序员对这些错误进行排查,就必须要支持调试这一功能,因此程序员开发中的程序一般都是debug版本,里面包含了各种调试信息,方便进行错误排查
  • 当程序员认为开发中的程序已经基本完成,就会将其交给测试组的人员进行测试。而这个程序最终肯定是要交给大众去使用的,使用这个程序的普通人显然不需要debug版本的调试信息,他们只需要更小的体积和更快的下载速度,因此这就要求程序需要一个**release发行版本,这个版本就是给测试组的人员进行测试和给用户进行使用的版本**

2.2 gdb常用功能及其选项

在这里插入图片描述

进入调试模式的命令为:

gdb file

  • file必须是一个debug版本的可执行程序

2.2.1 查看代码

命令:

l n

  • 查看第n行附近的10行代码
  • Enter可以继续查看

2.2.2 开始/退出调试

命令:

  • r:如果没有打断点,那么会正常运行代码;否则会运行到第一个断点处
  • quit:推出调试

2.2.3 断点设置

添加断点

  • b n:在第n行添加断点
  • b 函数名:在指定函数的入口处添加断点
  • b file:n:在指定文件的第n行添加断点。注意:这个file不是可执行程序,而是被编译的.c/.cpp文件

查看断点

info b

例如:

在这里插入图片描述

  • 第一列的数字Num表示断点的编号
  • 第四列的字符Enb表示断点的使能状态,y表示该断点处于开启状态,可被使用;n表示处于关闭状态,不可被使用

删除断点

d n:表示删除**编号为n**的断点。

  • 特别注意,删除断点是按编号删除,而不是按行号

使能断点

  • disable n:关闭编号为n的断点
  • enbale n:开启编号为n的断点

2.2.4 逐语句/逐过程

逐语句

  • 在C语言/C++中,被一个分号;分割的语句都被称为一条语句。逐语句调试就是一个个分号地,不做任何跳过的调试。

  • 因此逐语句调试可以进入函数体内调试。

命令:

s

逐过程

  • 一个函数成为一个过程
  • 因此逐过程调试不能进入函数体内进行调试

命令:

n

2.2.5 断点跳跃

如果打了多个断点,那我们可以通过命令直接运行到下一个断点处:

c

2.2.6 查看变量

p name:查看指定变量的内容

如果想要使变量一直显示,可以用命令:

display name

例如:

在这里插入图片描述

  • 变量前的数字即为该变量的编号

如果想删除常显示的变量,可以使用命令:

undisplay n:即删除编号为n的变量常显示

2.2.7 查看函数调用堆栈

命令:

bt

3. 自动划构建工具——makekfile&&make

在这里插入图片描述

Makefile和make是与Linux系统中软件编译和构建相关的工具。它们通常用于自动化构建过程,确保在源代码发生变化时只重新编译必要的部分,从而提高开发效率。

3.1 makefile

  • 也可以写为Makefile
  • makefile一个文本文件
  • makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂
    的功能操作

我们来通过一个具体的例子来学习一个makefile文件要包括哪些内容:

在这里插入图片描述

mybin:code.c

  • 这叫一组依赖关系mybin目标文件,code.c为依赖文件列表。
  • 表示mybin这个目标文件依赖于code.c这个文件列表而构建

gcc -o mybin code.c

  • 注意:前面必须有Tab缩进,这是语法要求
  • 这一行叫做依赖方法
  • 表示目标文件是通过gcc编译来完成对code.c这一依赖文件列表的依赖的

.PHONY:clean

  • clean设置成一个伪目标
  • 伪目标在任何时候都会执行,不会受时间戳限制

clean:

  • clean也是一个目标文件,但是没有对应的依赖文件列标
  • 其被修饰为了一个伪目标,表示一个命令操作——清除

rm -f mybin

  • 这就是clean的依赖方法,即clean对应的操作

makefile文件的其他写法

  • 在一组依赖关系和依赖方法中,目标文件可以被$@替换,依赖关系列表可以被$^替换,例如:

    在这里插入图片描述

  • makefile文件也允许我们定义变量和选项,例如:

    在这里插入图片描述

3.2 make

make是一个命令

3.2.1 工作原理

如果我们只输入一个make命令:

  • 会找到makefile中的第一个目标文件,然后根据依赖文件列表和依赖方法构建出目标文件

  • 如果依赖文件列表有文件不存在,那么会继续向下找这个不存在文件的依赖关系和依赖方法,知道构建出这个文件

  • 如果最终这个文件不能被构建,那么此次make命令就会报错

  • 例如:

    在这里插入图片描述

make后面也可以跟一个目标文件来执行指定的操作。例如:make clean

特别注意:

如果一个目标文件没有被.PYTHON修饰为伪目标,那么它的make构建就会收到时间戳的影响

  • 即,如果该文件的修改时间没有改变,那么就不会进行make构建

  • 例如,重复构建目标文件mybin,会报错:

    在这里插入图片描述

而提到修改时间,我们就有必要了解一个文件的acm时间

3.2.2 文件的acm时间

我们可以用命令查看一个文件的acm时间:

stat filename

在这里插入图片描述

  • Access:访问时间。即最后一次读写文件的时间
  • Modify:修改时间。即最后一次修改文件内容的时间。这个时间就是影响make构建的时间
  • Change:改变时间。文件 = 内容 + 属性,即最后一次改变文件内容或属性的时间。

我们也可以用命令来刷新一个文件的acm时间:

touch filename


本章完。
下一章,我们将进入Linux系统编程部分,各位如果感兴趣不妨点个关注。
请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

边缘计算是如何为元宇宙提供动力的?

构建元宇宙虚拟世界并不简单,也并不便宜,但是还是有许多大型公司正在转移大量资源来开发他们的元宇宙业务,当然大部分企业注意力都围绕着 VR 耳机、AR 眼镜、触觉手套和其他沉浸式虚拟现实体验所需的可穿戴硬件。虽然这种沉浸式的体验是最终结…

【Django使用】django经验md文档10大模块。第4期:Django数据库增删改查

Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以"插件"形式服务于整个框架,Django有许多功能强大的第三方插件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展…

WSL 2 更改默认安装的 Linux 发行版

目录 什么是 WSL 2?更改默认安装的 Linux 发行版更改发行版的 WSL 版本 什么是 WSL 2? WSL 2 是适用于 Linux 的 Windows 子系统体系结构的一个新版本,它支持适用于 Linux 的 Windows 子系统在 Windows 上运行 ELF64 Linux 二进制文件。 它的…

nn.KLDivLoss,nn.CrossEntropyLoss,nn.MSELoss,Focal_Loss

KL loss:https://blog.csdn.net/qq_50001789/article/details/128974654 https://pytorch.org/docs/stable/nn.html 1. nn.L1Loss 1.1 公式 L1Loss: 计算预测 x和 目标y之间的平均绝对值误差MAE, 即L1损失: l o s s 1 n ∑ i 1 , . . . n ∣ x i…

leetcode算法之分治-快排

目录 1.颜色分类2.排序数组3.数组中的第k个最大元素4.最小的k个数 1.颜色分类 颜色分类 class Solution { public:void sortColors(vector<int>& nums) {int n nums.size();int left -1,rightn,i0;while(i<right){if(nums[i] 0) swap(nums[left],nums[i]);e…

Spring的后处理器

目录 引言 BeanFactoryPostProcessor 注意 BeanPostProcessor 引言 Spring的后处理器是spring对外开发的重要扩展点&#xff0c;允许我们介入到Bean的整个实例化流程来&#xff0c;以达到动态注册BeanDefintion&#xff0c;动态修改BeanDefintion&#xff0c;以及动态修改Be…

【Android】使用Retrofit2发送异步网络请求的简单案例

添加网络权限到AndroidManifest.xml清单文件 为了让你的Android应用程序能够使用互联网进行通信&#xff0c;你需要在AndroidManifest.xml文件中添加网络权限声明。<uses-permission android:name"android.permission.INTERNET"/> 这个权限应该添加到 Android…

laravel-admin导出excel全部,表中无id列导出失败

laravel-admin导出excel时&#xff0c;导出全部数据&#xff0c;但是表中没有id字段&#xff0c;然后就无法导出excel&#xff1b; 就直接显示 一开始我也很着急&#xff0c;弄了半天还是不行&#xff0c;然后重写还是有问题 最后发现底层代码排序是按照id排序的orderBy(id, a…

音视频技术在手机上的应用与挑战

// 编者按&#xff1a;随着手机相机功能日益强大&#xff0c;4k&#xff0c;8k&#xff0c;各类特色短视频的拍摄&#xff0c;编辑、播放需求日益增长&#xff0c;短视频应用的火爆也对当前的手机音视频技术提出了更高的要求&#xff0c;如何更好地提高用户体验成为了行业共同…

Android 13 - Media框架(14)- OpenMax(二)

这一节我们将来解析 media.codec 这个 HIDL service 究竟提供了什么服务&#xff0c;服务是如何启动的。 1、main 函数 我们先来看 frameworks/av/services/mediacodec/main_codecservice.cpp&#xff1a; int main(int argc __unused, char** argv) {strcpy(argv[0], "…

微服务 Spring Cloud 7,Nacos配置中心的Pull原理,附源码

目录 一、本地配置二、配置中心1、以Nacos为例&#xff1a;2、Pull模式3、也可以通过Nacos实现注册中心 三、配置中心提供了哪些功能四、如何操作配置中心1、配置注册2、配置反注册3、配置查看4、配置变更订阅 五、主流的微服务注册中心有哪些&#xff0c;如何选择&#xff1f;…

76基于matlab的免疫算法求解配送中心选址问题,根据配送地址确定最佳配送中心地址位置。

基于matlab的免疫算法求解配送中心选址问题&#xff0c;根据配送地址确定最佳配送中心地址位置。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 76matlab免疫算法配送中心选址 (xiaohongshu.com)

常见Web安全

一.Web安全概述 以下是百度百科对于web安全的解释&#xff1a; Web安全&#xff0c;计算机术语&#xff0c;随着Web2.0、社交网络、微博等等一系列新型的互联网产品的诞生&#xff0c;基于Web环境的互联网应用越来越广泛&#xff0c;企业信息化的过程中各种应用都架设在Web平台…

SpringCloud总结

注&#xff1a;本文并不涉及具体功能是怎么实现的&#xff0c;而只是微服务技术栈的整体总结和理解。 目录 一.基础概念--认识微服务 1.单体架构 2.分布式架构 3.微服务 4.SpringCloud 二.服务的拆分原则 三.RestTemplate--实现不同服务之间的通信与远程调用 四.Eurek…

5 redis的GEO操作

一、GEO Redis 3.2版本提供了GEO(地理信息定位)功能&#xff0c;支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。 有效纬度从-85.05112878度到85.05112878度 注意&#xff1a;当坐标位置超出上述指定范围时&#xff0c;将会返回一个错误。 …

RTMP协议和源码解析

一、背景 实时消息传输协议&#xff08;Real-Time Messaging Protocol&#xff09;是目前直播的主要协议&#xff0c;是Adobe公司为Flash播放器和服务器之间提供音视频数据传输服务而设计的应用层私有协议。RTMP协议是目前各大云厂商直线直播业务所公用的基本直播推拉流协议&a…

高防CDN为什么可以防DDOS攻击

CDN的全称是ContentDeliveryNetwork&#xff0c;即内容分发网络&#xff0c;顾名思义&#xff0c;它是一个分布式节点网络(也称为边缘服务器)&#xff0c;CDN节点具有缓存内容的功能&#xff0c;使用户可以在不获取源服务器数据的情况下就近获取所需内容&#xff0c;提高客户访…

【LeetCode每日一题合集】2023.9.25-2023.10.1(⭐LFU缓存Java数据流花期内花的数量)

文章目录 460. LFU 缓存⭐&#xff08;数据结构题&#xff09;解法1——平衡树 哈希表&#xff08;TreeSet HashMap&#xff09; O ( l o g n ) O(logn) O(logn)解法2——双哈希表 双向链表 O ( 1 ) O(1) O(1) &#xff08;LRU缓存的升级版&#xff09; 2582. 递枕头解法—…

SpringCloud微服务注册中心:Nacos介绍,微服务注册,Ribbon通信,Ribbon负载均衡,Nacos配置管理详细介绍

微服务注册中心 注册中心可以说是微服务架构中的”通讯录“&#xff0c;它记录了服务和服务地址的映射关系。在分布式架构中&#xff0c;服务会注册到这里&#xff0c;当服务需要调用其它服务时&#xff0c;就这里找到服务的地址&#xff0c;进行调用。 微服务注册中心 服务注…

LV.12 D18 中断处理 学习笔记

一、ARM的异常处理机制及工程代码结构 1.1异常概念 处理器在正常执行程序的过程中可能会遇到一些不正常的事件发生 这时处理器就要将当前的程序暂停下来转而去处理这个异常的事件 异常事件处理完成之后再返回到被异常打断的点继续执行程序。 1.2异常处理机制 不同的处…