当前位置: 首页 > news >正文

【Linux】编译器gcc g++和调试器gdb的使用

文章目录

  • 1.编译器gcc/g++
    • 1.1C语言程序的翻译过程
      • 1.预处理
      • 2.编译
      • 3.汇编
      • 4. 链接
    • 1.2 链接方式与函数库
      • 1.动态链接与静态链接
      • 2.动态库与静态库
    • 1.3 gcc与g++的使用
  • 2.调试器gdb
    • 2.1debug和release
    • 2.2gdb的安装
    • 2.3gdb的使用
    • 2.4gdb的常用指令
  • 3.总结

1.编译器gcc/g++

1.1C语言程序的翻译过程

1.预处理

在此阶段做的事情:

  1. 头文件展开:把我们编写的代码中的包含头文件的代码替换成头文件本身
  2. 删除所有的注释
  3. #define定义的符号和宏全部替换
  4. 执行条件编译

在Linux下,我们可以通过指令让gcc只执行预处理操作

gcc -E test.c -o test.i
# -E 表示从现在开始,进行程序的翻译,当预处理结束时停下来
# -o 表示指明产生的文件的名称

image-20230227224027072

可以看到经过预编译之后,#include包含头文件的代码没有了,但是文件中多了几百行,这些多的就是头文件的内容被拷贝进来了,注释部分被删除,宏定义被替换了,条件编译也转变成了执行过后的结果。

2.编译

此阶段做的事情:

  • 语法分析
  • 词法分析
  • 语义分析
  • 符号汇总

最终的结果就是把C语言代码变成汇编语言代码

在Linux下需要执行的指令是:

gcc -S test.i -o test.s
# -S 表示从现在开始,执行程序的翻译,做完编译工作之后,变成汇编代码就停下来
# 变成的汇编代码的后缀名是.s

image-20230227221608377

打开test.s之后我们可以发现,里面的代码意见已经变成汇编指令了。

3.汇编

此阶段做的事情:把汇编代码变成二进制(这里的二进制不是可执行的,叫做二进制目标文件)

在Linux下需要执行的指令是:

gcc -c test.s -o test.o
# -c 表示从现在开始,进行程序的翻译,做完汇编工作,变成可重定向的目标二进制,就停下来
# 重定向的目标二进制文件的后缀名是.o

image-20230227222129347

可以看到,此时文件内已经变成了我们看不懂的二进制代码,当他以二进制的形式打开时,是这样的

image-20230227222425180

4. 链接

此阶段做的事情:把本地编写的代码和c标准库中的代码合并,形成可执行的二进制文件

  • 合并段表:编译器会把在汇编阶段生成的多个目标文件中相同格式的数据合并在一起,最终形成一个 .exe 文件。
  • 符号表的合并和重定位:符号表的合并是指编译器会把在汇编阶段生成的多个符号表合并为一个符号表;重定位则是指当同一个符号出现在两个符号表中时,编译器会选取其中和有效地址相关的那一个,舍弃另外一个

在Linux下需要执行的指令是:

gcc test.o -o mytest
# 链接阶段是程序翻译的最后一个阶段,不需要加任何选项
# 默认生成的可执行文件的文件名是a.out,我们可以通过-o选项指定

image-20230227223200457

可以看到,产生的文件mytest就是可执行的程序。

注:

  1. 对于上述的几个Linux下gcc指令的选项和产生文件的后缀名,这里有一个方便记忆的小技巧,预编译、编译、链接的选项分别是ESc,对应着键盘左上角的按键Esc,产生的文件后缀名是iso,对应着光盘映像文件的后缀名
  2. 上述的分段执行只是为了方便我们能够更加细致的看到程序翻译的过程,在实际使用gcc的时候,只需要使用指令gcc 原文件名 -o 产生的可执行文件名或者gcc 原文件名即可。

1.2 链接方式与函数库

1.动态链接与静态链接

我们在写代码的过程中,会经常用到库函数,类似printf,scanf,strlen等函数,这些函数在我们的代码中只是调用了它们,并没有实现,那么是谁实现的呢?答案是库函数,是别人预先写好的

同时,程序在预处理、编译和汇编阶段处理的都是我们自己编写的代码,只有在链接的时候,库函数的实现才会和我们的代码关联起来 (符号表的重定位);所以,链接的本质是我们在调用库函数时如何与标准库相关联的问题

程序的链接方式一共有两种:动态链接与静态链接

  • 动态链接是指执行代码时,如果遇到库函数调用就跳转到动态库中对应函数的定义处,然后执行该函数,执行完毕后再跳转回原程序并继续往下执行;它的优点是形成的可执行程序小,缺点是受到动态库变动 (删除、升级等) 的影响

  • 静态链接则是直接将本程序内部要使用的库函数从对应的静态库中拷贝一份过来;它的优点是不与静态库产生关联,即不受静态库变动 (删除、升级等) 的影响;缺点是形成的可执行程序非常大。

2.动态库与静态库

函数库是一些事先写好的,用于给别人复用的函数的集合,函数库一般分为静态库和动态库两种

静态库是指在编译链接时,把包含的库文件全部拷贝到可执行文件中,然后在运行时就不再需要库文件了,但是由于拷贝了全部内容,所以生成的文件会很大。静态库在Linux下的后缀名是.a,在Windows下后缀名是.lib

动态库:也叫共享库,与静态库相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为.so,在Windows下后缀名是.dll

那么,我们验证一下,我们在Linux下编译是怎么链接的

验证方法:使用file指令可以看到调用的库是动态库还是静态库

image-20230301000408464

我们可以看到,gcc默认的链接方式是动态链接,那么怎么让它使用静态链接呢?只需要在编译指令后面加上-static

image-20230301000647594

这个时候,我们查看一下两个文件的详细信息

image-20230301000746827

可以看到,使用静态链接产生的可执行文件,大小比动态链接产生的文件大得多。

这里补充一点非常重要的事情:一定不要删除系统中的C动态库,因为Linux系统中的基本上所有指令都是使用C语言写的,如果没有C动态库,会导致很多指令都无法使用,最终的解决方案只能是重装系统。

1.3 gcc与g++的使用

gcc 选项

  • -E 只激活预处理,这个不生成文件,你需要把它重定向到一个输出文件里面
  • -S 编译到汇编语言不进行汇编和链接
  • -c 编译到目标代码
  • -o 文件输出到 文件
  • -static 此选项对生成的文件采用静态链接
  • -g 生成调试信息。GNU 调试器可利用该信息。
  • -shared 此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库.
  • -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高
  • -w 不生成任何警告信息。
  • -Wall 生成所有警告信息

我们在使用静态链接的方式编译的时候,可能会发现报错,因为有部分Linux机器没有安装C静态库,所以需要我们手动安装

# 手动安装C静态库
sudo yum install -y glibc-static

同时,部分Linux机器也是没有安装g++的,也需要我们手动安装

# 安装g++
sudo yum install -y gcc-c++
# 安装c++静态库
sudo yum install -y libstdc++-static

2.调试器gdb

2.1debug和release

debug和release是程序编译的类型版本,debug是调试版本,其中包含了程序的调试信息,release是程序的发布版本,其中没有调试信息,并且进行了部分优化(例如对死循环的优化)。

image-20230307154214967

可以看到,debug版本比release版本要大一点,其中多的内容就是调试信息,所以gdb调试必须要在debug模式下调试,如果是release版本下不可执行调试

image-20230307154708380

会显示no debugging symbols found(没有找到调试标志)

Linux下gcc/g++编译出来的程序默认是release版本

到这里我们总结一下之前所学到的关于Linux下的一些默认行为

  1. gcc/g++的默认行为

    • 默认连接方式是动态连接(静态链接需要加-static)

    • 默认编译版本是release(编译debug版本需要加-g)

  2. vim的默认行为

    • 打开后的默认模式是命令模式

2.2gdb的安装

sudo yum install -y gdb

image-20230307155740754

2.3gdb的使用

  • 第一步:使用-g指令编译源代码,产生debug版本的可执行程序

    image-20230307160313457

  • 第二步:执行gdb FileName进入调试

    image-20230307160551534

  • 第三步:输入调试指令进行调试即可

  • 第四步:ctrl+d或者q/quit退出调试

2.4gdb的常用指令

  • list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。
  • list/l 函数名:列出某个函数的源代码。
  • r或run:运行程序。
  • n 或 next:单条执行。
  • s或step:进入函数调用
  • break(b) 行号:在某一行设置断点
  • break 函数名:在某个函数开头设置断点
  • info break :查看断点信息。
  • finish:执行到当前函数返回,然后挺下来等待命令
  • print§:打印表达式的值,通过表达式可以修改变量的值或者调用函数
  • p 变量:打印变量值。
  • set var:修改变量的值
  • continue(或c):从当前位置开始连续而非单步执行程序
  • run(或r):从开始连续而非单步执行程序
  • delete breakpoints:删除所有断点
  • delete breakpoints n:删除序号为n的断点
  • disable breakpoints:禁用断点
  • enable breakpoints:启用断点
  • info(或i) breakpoints:参看当前设置了哪些断点
  • display 变量名:跟踪查看一个变量,每次停下来都显示它的值
  • undisplay:取消对先前设置的那些变量的跟踪
  • until X行号:跳至X行
  • breaktrace(或bt):查看各级函数调用及参数
  • info(i) locals:查看当前栈帧局部变量的值
  • quit:退出gdb

下面会使用实例来演示部分指令

image-20230307161817138

  • list/l 行号:显示binFile源代码,接着上次的位置往下列,每次列10行。

    image-20230307162703430

  • list/l 函数名:列出某个函数的源代码

    image-20230307162759348

  • break(b) 行号:在某一行设置断点

  • info break :查看断点信息

  • break 函数名:在某个函数开头设置断点

    image-20230307163145936

  • d + 断点编号:删除断点

  • delete breakpoints:删除所有断点

    image-20230307164814166

  • r或run:运行程序

    image-20230307163331719

  • s或step:进入函数调用

    image-20230307163447046

    进入了AddToVal函数内部,遇到断点停下

  • n 或 next:单条执行

    image-20230307163634833

    每个n执行一行

  • print§:打印表达式的值,通过表达式可以修改变量的值或者调用函数

    image-20230307163850478

  • display 变量名:跟踪查看一个变量,每次停下来都显示它的值

    image-20230307164008886

  • undisplay:取消对先前设置的那些变量的跟踪

    image-20230307164201532

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

    image-20230307164252125

3.总结

到此,我们学习了Linux下的基本指令与操作,权限相关的概念,学习了yum工具,能够在Linux下进行软件的安装,学习了vim的使用,能够在Linux下写代码,学习了gcc/g++的使用,能够在Linux下编译代码,学习了gdb的使用,能够在Linux下调试代码,学习了make/makefile,能够在Linux下使用多文件编程,为我们在Linux下编程提供了便利,编写了我们的第一条Linux程序----进度条,学会了使用git命令行,能够把Linux下的代码上传到Gitee/Github上。Linux的工具篇到此结束,下面,我们将会遇到Linux的第一座大山----进程。

抬头是山,路在脚下,与诸君共勉

本章完

相关文章:

【Linux】编译器gcc g++和调试器gdb的使用

文章目录1.编译器gcc/g1.1C语言程序的翻译过程1.预处理2.编译3.汇编4. 链接1.2 链接方式与函数库1.动态链接与静态链接2.动态库与静态库1.3 gcc与g的使用2.调试器gdb2.1debug和release2.2gdb的安装2.3gdb的使用2.4gdb的常用指令3.总结1.编译器gcc/g 1.1C语言程序的翻译过程 1…...

高效能自动化港口数字化码头智慧港航,中国人工智能企业CIMCAI世界港航人工智能领军者,成熟港口码头人工智能产品中国人工智能企业

打造高效能自动化港口数字化码头智慧港航,中国人工智能企业CIMCAI中集飞瞳世界港航人工智能领军者,成熟港口码头人工智能产品全球顶尖AI科技CIMCAI成熟AI产品全球前三船公司及港口落地,包括全球港口/堆场智能闸口验箱,全球港口岸边…...

HTTP协议(一)

HTTP协议(一) 什么是HTTP协议 客户端连上web服务器后,如果想要获得web服务器中的某个web资源,需要遵守一定的通讯格式,HTTP协议用于定义客户端与web服务器之间通讯的格式;基于TCP连接的传输协议&#xff…...

计算神经网络参数量Params、计算量FLOPs(亲测有效的3种方法)

1.stat(cpu统计) pip install torchstat from torchstat import statstat(model, (3, 32, 32)) #统计模型的参数量和FLOPs,(3,32,32)是输入图像的size 结果: 问题:当网络中有自定义参数时&am…...

sizeof与一维数组和二维数组

🍕博客主页:️自信不孤单 🍬文章专栏:C语言 🍚代码仓库:破浪晓梦 🍭欢迎关注:欢迎大家点赞收藏关注 sizeof与一维数组和二维数组 文章目录sizeof与一维数组和二维数组前言1. sizeof与…...

Spark UI

Spark UIExecutorsEnvironmentStorageSQLExchangeSortAggregateJobsStagesStage DAGEvent TimelineTask MetricsSummary MetricsTasks展示 Spark UI ,需要设置配置项并启动 History Server # SPARK_HOME表示Spark安装目录 ${SPAK_HOME}/sbin/start-history-server…...

windows应用(vc++2022)MFC基础到实战(2)

目录向导和资源编辑器使用 MFC 应用程序向导创建 MFC 应用程序使用类视图管理类和 Windows 消息使用资源编辑器创建和编辑资源生成 MFC 应用程序的操作1.创建一个主干应用程序。2.了解即使在不添加你自己的任何一行代码的情况下,框架和 MFC 应用程序向导也能提供的内…...

记一次反射型XSS

记一次反射型XSS1.反射型XSS1.1.前言1.2.测试过程1.3.实战演示1.3.1.输入框1.3.2.插入代码1.3.3.跳转链接2.总结1.反射型XSS 1.1.前言 关于这个反射型XSS,利用的方式除了钓鱼,可能更多的就是自娱自乐,那都说是自娱自乐了,并且对系…...

BUUCTF-[羊城杯 2020]Bytecode

题目下载:下载 这道题是一个关于python字节码的。 补充一下相关知识:https://shliang.blog.csdn.net/article/details/119676978dis --- Python 字节码反汇编器 — Python 3.7.13 文档 手工还原参考:[原创]死磕python字节码-手工还原python源码-软件逆…...

《Uniapp入门指南:从安装到打包的全流程》

Uniapp是一款基于Vue.js的跨平台开发框架,可以快速构建出同时支持多个移动端平台和Web端的应用程序。本文将介绍Uniapp的基础知识和开发流程,帮助读者快速入门Uniapp开发。一、Uniapp的基础知识1.Uniapp的优势Uniapp的最大优势是可以快速开发同时支持多个…...

机器学习算法集成系统

版权所有:CSDN——川川菜鸟 本系统并不作为本专栏要求,这一篇自愿学习。 文章目录 本系统设计背景设计思路完整代码本系统设计背景 随着人工智能技术的不断发展,机器学习成为了人工智能领域的重要组成部分。机器学习算法能够从大量数据中发现模式、规律,并利用这些规律对新…...

scratch绘制雷达 电子学会图形化编程scratch等级考试三级真题和答案解析2022年9月

目录 scratch绘制雷达 一、题目要求 1、准备工作 2、功能实现 二、案例分析...

VRRP主备备份

1、VRRP专业术语 VRRP备份组框架图如图14-1所示: 图14-1:VRRP备份组框架图 VRRP路由器(VRRP Router):运行VRRP协议的设备,它可能属于一个或多个虚拟路由器,如SwitchA和SwitchB。虚拟路由器(Virtual Router):又称VRR…...

【软件逆向】软件破解?病毒木马?游戏外挂?

文章目录课前闲聊认识CTF什么是CTFCTF解题模式什么是逆向定义应用领域CTF中的逆向现状推荐书籍学习要点逆向工程学习基础常规逆向流程阶段一:信息收集阶段二:过保护后静态调试阶段三:结合动态调试阶段四:写解题脚本逆向例题概览1-控制台程序解题过程2-Crackme3-游戏4-移动安全C…...

curl请求常用参数和返回码

curl是一个用于传输数据的工具,支持各种协议,如HTTP、FTP、SMTP等。以下是一些常用的curl请求参数及其作用: -X, --request:指定HTTP请求方法,常见的有GET、POST、PUT、DELETE等。 -H, --header:设置HTTP请…...

【STM32】进阶(一):抢占式优先级和响应式优先级(NVIC_PriorityGroupConfig)

1、简介 STM32(Cortex-M3)中每个中断源都有两级优先级:抢占式优先级(pre-emption priority)和子优先级(subpriority),子优先级也叫响应式优先级。 1.1 抢占式优先级 望文知义,就是优先级高的…...

LogCompilation后JIT输出文件格式解析

https://wiki.openjdk.org/display/HotSpot/LogCompilationoverview https://spotcodereviews.com/articles/optimization/2020/12/23/why-does-the-jit-continually-recompile-the-same-method.html task_queued count表示总共执行次数,iicount表示解释器执行次数…...

Linux学习第二十四节-Podman容器

一、容器的概念 容器是由一个或多个与系统其余部分隔离的进程组成的集合。我们可以理解为“集装箱”。 集装箱是打包和装运货物的标准方式。它作为一个箱子进行标记、装载、卸载,以及从一个 位置运输到另一个位置。该容器的内容与其他容器的内容隔离&#xff0c…...

基于quartz实现定时任务管理系统

基于quartz实现定时任务管理系统 背景 说起定时任务框架,首先想到的是Quartz。这是定时任务的老牌框架了,它的优缺点都很明显。借助PowerJob 的readme文档的内容简单带过一下这部分。 除了上面提到,还有elastic-job-lite、quartzui也是相当…...

vue-element-admin:基于element-ui 的一套后台管理系统集成方案

文章目录一、vue-element-admin1、vue-element-admin1.1简介1.2安装2、vue-admin-template2.1简介2.2安装一、vue-element-admin 1、vue-element-admin 1.1简介 vue-element-admin是基于element-ui 的一套后台管理系统集成方案。 GitHub地址:https://github.com…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...