【Linux】深度解析与实战应用:GCC/G++编译器入门指南

🔥 个人主页:大耳朵土土垚
🔥 所属专栏:Linux系统编程

这里将会不定期更新有关Linux的内容,欢迎大家点赞,收藏,评论🥳🥳🎉🎉🎉

文章目录

  • 1. gcc/g++简介
  • 2. gcc/g++的基本使用
  • 3. 函数库
  • 4. 调试
  • 5. 总结

1. gcc/g++简介

  在Linux系统中,GCC(GNU Compiler Collection)是极其重要且广泛使用的编译器,它支持多种编程语言,包括C、C++、Objective-C、Java、Fortran等。GCC以其高效、灵活和跨平台的特点赢得了开发者的青睐。本文将详细介绍GCC中的C编译器gcc和C++编译器g++的基本使用方法和编译过程。

  GCC(GNU Compiler Collection)是一个由GNU项目开发的编译器套件,原名GNU C Compiler,但随着发展,它已支持多种编程语言的编译。GCC最初只能编译C语言,但现在的GCC通过不同的前端模块支持多种语言。GCC支持多种硬件平台,并且具备跨平台交叉编译的能力。

  在Linux系统中,gcc和g++是GCC套件中用于编译C和C++程序的工具。gcc专门用于C语言程序的编译,而g++则专注于C++程序的编译。虽然两者在编译C程序时可能表现相似,但在处理C++程序时,g++会链接C++的标准库,而gcc默认链接C的标准库。


2. gcc/g++的基本使用

gcc和g++的基本使用格式如下:

gcc [选项] 要编译的文件 [选项] [目标文件]  
g++ [选项] 要编译的文件 [选项] [目标文件]

我们可以通过下面的指令来判断是否已经安装gcc/g++:

gcc --version  
g++ --version

如果没有安装,大家可以先搜索安装gcc/g++对应的指令进行安装,因为不同的Linux发行版本安装指令或多或少有些差异,所以这里就不过多介绍。

gcc和g++的一些常用的选项包括:

-E:仅进行预处理,不进行编译和汇编。
-S:生成汇编代码,但不进行汇编和链接。
-c:生成目标代码(.o文件),但不进行链接。
-o:指定输出的文件名。
-static:使用静态链接生成可执行文件。
-g:生成调试信息,供GDB等调试器使用。

首先对于一个C或C++程序从源代码到可执行文件的编译过程通常包括四个步骤:预处理、编译、汇编和链接。

✨【预处理(进行宏替换)】:
  预处理功能主要包括宏定义,文件包含(#include)、条件编译(如#ifdef、#ifndef、#endif)以及删除注释等。

实例:

gcc -E hello.c -o hello.i
  • 这条命令会生成一个预处理后的文件hello.i,其中包含了所有宏展开和文件包含的结果;
  • hello.c 是要预处理的文件;
  • 选项“-E”,该选项的作用是让 gcc在预处理结束后停止编译过程;
  • 选项“-o”指向目标文件hello.i;
  • hello.i文件为已经预处理的C原始程序也就是目标文件。

✨【编译(生成汇编)】:
  在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。

实例:

gcc -S hello.i -o hello.s
  • 这条命令会生成一个汇编文件hello.s;
  • hello.i 是要编译的文件;
  • 选项“-S”,该选项的作用是让 gcc在预处理、编译后停止进行汇编,生成汇编代码
  • 选项“-o”指向目标文件hello.s;
  • hello.s文件为已经编译后的目标文件。

✨【汇编(生成机器可识别代码)】:
  汇编阶段将汇编代码转换成机器可以直接识别的二进制代码(目标代码)。也就是把编译阶段生成的“.s”文件转成为“.o”的二进制目标代码。

实例:

 gcc -c hello.s -o hello.o
  • 这条命令会生成一个目标文件hello.o,它是二进制文件,但还不能直接执行;
  • hello.s 是要汇编的文件;
  • 选项“-o”,该选项的作用是让 gcc在预处理、编译、汇编后停止进行链接,生成二进制目标代码;
  • 选项“-o”指向目标文件hello.o;
  • hello.o文件为已经汇编后的目标文件。

✨【链接(生成可执行文件或库文件)】:
  在成功编译之后,就进入了链接阶段。链接阶段将目标代码与程序所需的库(如C标准库libc.so.6)合并,生成最终的可执行文件。

实例:

gcc hello.o -o hello
  • 这条命令将hello.o与必要的库链接,生成可执行文件hello。
  • hello.o 是要链接的文件;
  • 选项“-o”指向目标文件hello;
  • hello文件为已经链接后的目标文件。

通常情况下我们都是直接使用gcc hello.c -o hello命令来将.c源文件直接一次性生成最终的可执行文件。

3. 函数库

  • 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
  • 这是因为系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。

在编译过程中,程序可能会调用标准库或其他第三方库中的函数。这些函数的具体实现在库中,而编译时生成的目标文件仅包含对这些函数的引用。链接器(Linker)负责将这些引用与库中的实际实现关联起来。

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

  • 静态库在编译时将库代码直接复制到可执行文件中,因此生成的可执行文件较大,但运行时不再需要库文件,其后缀名一般为“.a”。
  • 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,由操作系统动态加载。这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。

4. 调试

  在Linux操作系统的软件开发中,调试是一个至关重要的环节。它帮助开发者定位和解决程序中的错误、优化代码性能以及深入理解程序的运行过程。Linux提供了GDB(GNU Debugger)作为强大的调试工具,可以帮助开发者在程序运行时查找和修复错误。

  GDB是GNU项目的一部分,是一款功能强大的程序调试工具,支持多种编程语言,包括C、C++、Ada等。它允许开发者在程序运行时暂停执行、检查程序的状态(如变量值、寄存器状态、内存内容等)、单步执行代码以及修改程序中的数据,从而帮助开发者定位问题所在。

  在Linux环境下,使用GCC(GNU Compiler Collection)或G++(GCC的C++编译器)编译程序时,可以选择不同的编译模式来优化程序或保留调试信息。这些模式主要包括debug模式和release模式。

  • Release模式

在Release模式下,编译器会进行各种优化,以减少程序的大小、提高运行速度和效率。这些优化可能包括代码重排、循环展开、内联函数等。在Release模式下编译的程序通常不包含调试信息,因此程序体积更小,运行更快,但更难进行调试。

  • Debug模式

Debug模式则相反,它主要是为了调试程序而设计的。在Debug模式下,编译器会生成包含大量调试信息的二进制文件,这些调试信息包括源代码的行号、变量名、函数名等,这些信息对于使用调试器(如GDB)来跟踪程序执行、检查变量值、设置断点等非常有用。

  • GCC/G++的-g选项

-g选项是GCC/G++编译器的一个非常关键的选项,它告诉编译器生成调试信息。默认情况下(即不指定-g选项时),GCC/G++会以类似于Release模式的方式编译程序,即进行优化但不包含调试信息。如果你想要使用GDB等调试工具来调试你的程序,你需要在编译时加上-g选项。这样,GCC/G++就会生成包含调试信息的二进制文件。例如:

g++ -g my_program.cpp -o my_program

这条命令会编译my_program.cpp文件,并生成一个名为my_program的二进制文件,该文件包含了调试信息,因此可以使用GDB进行调试。

总之,Linux gcc/g++出来的二进制程序,默认是release模式,要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项。

GDB的基本使用方法

首先可以使用sudo yum install -y gdb命令来安装gdb:

出现complete字样则表明安装成功🥳🥳

  1. 启动GDB

使用GDB调试程序非常简单,只需在命令行中输入gdb命令后跟程序名即可。例如,要调试名为test的程序,可以输入:

gdb test
  1. 设置断点

在GDB中,断点是最常用的功能之一。它允许程序在执行到特定行时暂停。可以通过break(简写为b)命令设置断点。例如,在程序第10行设置断点:

(gdb) b 10

或者,如果知道函数名,也可以直接在函数处设置断点:

(gdb) break main
  1. 查看断点

使用info breakpoints命令这是查看断点信息的最直接方式。在GDB命令行中输入info breakpoints(或简写为info b),GDB会列出所有已设置的断点信息,包括断点的编号、类型、是否启用、地址以及断点所在的源代码位置等。

(gdb) info b 

在这个示例中,Num是断点的编号,Type是断点的类型(这里是普通的断点),Disp是断点处理后的行为(keep表示断点保持活动状态),Enb表示断点是否启用(y表示启用),Address是断点所在的内存地址,What是断点所在的源代码位置。

如果你只对某个特定的断点感兴趣,可以使用info breakpoint 编号命令来查看该断点的详细信息。其中,“编号”是你想要查看的断点的编号。

(gdb) info breakpoint 1

这个命令会展示编号为1的断点的详细信息,与info breakpoints类似,但只针对这一个断点。

  1. 删除断点

delete 断点编号:删除指定编号的断点。
clear 文件名:行号:删除指定文件和行号上的断点。

此外:
disable breakpoints:禁用断点
enable breakpoints:启用断点

  1. 运行程序

设置好断点后,可以使用run(简写为r)命令启动程序。程序会在遇到第一个断点时暂停。

  1. 查看变量

查看变量值:使用print(简写为p)命令可以查看变量的当前值。例如,查看变量x的值:

(gdb) print x

display 变量名:跟踪查看一个变量,每次停下来都显示它的值
undisplay:取消对先前设置的那些变量的跟踪

  1. until X行号:跳至X行

  2. 查看调用栈

使用backtrace(简写为bt)命令可以查看当前的函数调用栈。

  1. 查看寄存器

通过info registers命令可以查看当前寄存器的状态。

  1. 单步执行

next(简写为n):执行下一行代码,如果当前行有函数调用,不会进入函数内部。
step(简写为s):执行下一行代码,如果当前行有函数调用,会进入函数内部。

  1. 继续执行

使用continue(简写为c)命令可以让程序继续执行,直到遇到下一个断点或程序结束。

  1. 执行到当前函数

finish:执行到当前函数返回,然后停下来等待命令

  1. 列出源码

list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
list/l 函数名:列出某个函数的源代码。


  1. 退出GDB

使用quit(简写为q)命令退出GDB。

GDB的高级技巧

  1. 条件断点

可以设置仅在特定条件下触发的断点。例如,当变量x等于10时暂停:

(gdb) break 10 if x == 10
  1. 观察点

与断点不同,观察点是在变量值发生变化时暂停程序。使用watch命令设置来观察变量的值:

(gdb) watch x
  1. 反汇编查看

使用disassemble(简写为disas)命令可以查看函数的汇编代码,有助于理解底层执行流程。

  1. 核心转储文件调试

当程序崩溃时,Linux系统会自动生成一个核心转储文件(core dump)。GDB可以加载这个文件进行调试,帮助开发者分析崩溃原因。

  1. 远程调试

GDB支持通过TCP/IP连接远程目标机进行调试,非常适合嵌入式系统或分布式系统的开发。

GDB作为一款功能强大的调试工具,为Linux环境下的软件开发提供了极大的便利。掌握GDB的基本使用方法和高级技巧,对于提升开发效率、保证软件质量具有重要意义。


5. 总结

  GCC是Linux下极其重要的编译器,通过gcc和g++,开发者可以方便地将C和C++源代码编译成可执行文件。了解GCC的编译过程和常用选项,对于Linux下的软件开发至关重要。此外通过GDB进行调试,可以进一步帮助开发者定位和解决程序中的错误。

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

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

相关文章

RabbitMQ08_保证消息可靠性

保证消息可靠性 一、生产者可靠性1、生产者重连机制(防止网络波动)2、生产者确认机制Publisher Return 确认机制Publisher Confirm 确认机制 二、MQ 可靠性1、数据持久化交换机、队列持久化消息持久化 2、Lazy Queue 惰性队列 三、消费者可靠性1、消费者…

速通LLaMA3:《The Llama 3 Herd of Models》全文解读

文章目录 概览论文开篇IntroductionGeneral OverviewPre-TrainingPre-Training DataModel ArchitectureInfrastructure, Scaling, and EfficiencyTraining Recipe Post-TrainingResultsVision ExperimentsSpeech Experiments⭐Related WorkConclusionLlama 3 模型中的数学原理1…

细说硫酸钙防静电地板的材质结构和优势特点

防静电地板有全钢基材的、硫酸钙基材的、铝合金基材的,在一些防静电要求、承载要求、铺设要求、铺装效果要求很高的场合,如银行、电信机房、移动机房、智能化办公室、部队指挥中心,通常都会使用硫酸钙防静电地板。那么什么是硫酸钙防静电地板…

计算机毕业设计 二手图书交易系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

计算机毕业设计 基于Python的医疗预约与诊断系统 Django+Vue 前后端分离 附源码 讲解 文档

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…

arthas-阿里远程诊断工具神器一定要掌握

文章目录 1. 背景介绍2. 安装下载3. 常用命令4. 常见案例4.1 案例一:使用logger 实时修改某个类的日志级别、4.2 案例二:使用watch 查看方法输入输出参数4.3 案例三:使用 Arthas 实现在线代码热更新 1. 背景介绍 通常,本地开发环…

文件上传、amrkdown编辑器

一、文件上传 这里我以图片为例,进行上传,上传到阿里云oss(对象存在中) 首先,我们先梳理一下,图片上传的流程 1、前端选择文件,提交文件 前端提交文件,我们可以使用ElementUI中的…

蓝队技能-应急响应篇Web内存马查杀JVM分析Class提取诊断反编译日志定性

知识点: 1、应急响应-Web内存马-定性&排查 2、应急响应-Web内存马-分析&日志 注:传统WEB类型的内存马只要网站重启后就清除了。 演示案例-蓝队技能-JAVA Web内存马-JVM分析&日志URL&内存查杀 0、环境搭建 参考地址:http…

有关 签到/签退 业务逻辑 的梳理与学习

导言 最近搞到了个签到管理,其中的业务逻辑感觉有点复杂(可能是我的方向不对),虽然是实现了,不过代码和逻辑很多,也有些乱,想趁着还记得逻辑来记录梳理一下,看看自己以后有没有更好的思路,或者有大佬有思路…

[C#]winform 使用opencvsharp实现玉米粒计数

【算法介绍】 这段代码是使用OpenCvSharp库(OpenCV的C#封装)对图像进行处理,主要流程包括图像的二值化、腐蚀操作、距离变换、轮廓检测,并在原图上标出检测到的轮廓位置及数量。下面是对代码的详细解读: 初始化&…

Ubuntu22.04安装GNSS数据处理软件GAMIT/GLOBK

由于微信公众号改变了推送规则,为了每次新的推送可以在第一时间出现在您的订阅列表中,记得将本公众号设为星标或置顶喔~ 手把手带您安装gamit/globk软件~ 🌿前言 受朋友之托,出一期Ubuntu22.04安装GNSS数据处理软件——gamit软件…

【论文笔记】Are Large Kernels Better Teacheres than Transformers for ConvNets

Abstract 本文提出蒸馏中小核ConvNet做学生时,与Transformer相比,大核ConvNet因其高效的卷积操作和紧凑的权重共享,使得其做教师效果更好,更适合资源受限的应用。 用蒸馏从Transformers蒸到小核ConvNet的效果并不好,原…

MySQL篇(存储过程 触发器 存储函数)(持续更新迭代)

目录 一、存储过程 1. 简介 2. 特点 3. 语法 3.1. 创建 3.2. 调用 3.3. 查看 3.4. 删除 4. 示例 二、变量 1. 简介 2. 系统变量 2.1. 查看系统变量 2.2. 设置系统变量 2.3. 演示示例 3. 用户定义变量 3.1. 赋值 方式一 方式二 3.2. 使用 3.3. 演示示例 4.…

Rust - 字符串:str 与 String

在其他语言中,字符串通常都会比较简单,例如 “hello, world” 就是字符串章节的几乎全部内容了。 但是Rust中的字符串与其他语言有所不同,若带着其他语言的习惯来学习Rust字符串,将会波折不断。 所以最好先忘记脑中已有的关于字…

华为---代理ARP简介及示例配置

目录 1. 概念 2. 前提条件 3. 使用环境 4. 工作过程 5. 优点 6. 缺点 7. 示例配置 7.1 示例场景 7.2基本配置 7.3 配置端口隔离 7.4 开启代理ARP 7.4.1 VLAN内代理ARP 7.4.2 VLAN间代理ARP 7.4.3路由式ARP代理 1. 概念 代理ARP(Proxy ARP)&…

C#使用实体类Entity Framework Core操作mysql入门:从数据库反向生成模型

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的,可以在任何平台上使用。 源码指引:github源…

matlab恢复默认窗口布局

1.点击主页,选择布局 2.选择默认,即可恢复到默认的窗口布局

LIN总线CAPL函数—— 设置LIN报文字节间隔长度(linSetInterByteSpace)

🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】🍅 玩转CANoe&…

利士策分享,如何培养良好的工作习惯?

利士策分享,如何培养良好的工作习惯? 在这个快节奏、高压力的职场环境中,培养良好的工作习惯不仅关乎个人职业发展的顺畅度, 更是提升工作效率、保持身心健康的关键。 以下是一些实用的建议,帮助你在日常工作中逐步构…

智慧水利采砂船在线监控平台:构建高效、智能的河道采砂监管体系

随着科技的不断发展,水利行业的智慧化转型也日益受到重视。智慧水利采砂船在线监控平台便是这一转型的重要成果之一。该平台主要服务于水政执法人员,针对取得河道采砂许可证的采砂公司及采砂船,实施在线自动监控,旨在提高监管效率…