当前位置: 首页 > 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…...

KVM-7、KVM 虚拟机创建的几种方式

通过对 qemu-kvm、libvirt 的学习,总结三种创建虚拟机的方式: (1)通过 qemu-kvm 创建 (2)通过 virt-install 创建 (3)通过 virt-manager 创建 在使用这三种创建虚拟机前提是 宿主机必须支持 cpu 的硬件虚拟化技术(Intel 是 vmx,AMD 是svm),通过下面方式进行查看…...

Hadoop三大框架之HDFS

一、概述HDFS产生的背景及定义HDFS产生背景随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,需要一种系统来管理多台机器上的文件,这就是分布式文件…...

好好的系统,为什么要分库分表?

不急于上手实战 ShardingSphere 框架,先来复习下分库分表的基础概念,技术名词大多晦涩难懂,不要死记硬背理解最重要,当你捅破那层窗户纸,发现其实它也就那么回事。 什么是分库分表 分库分表是在海量数据下&#xff0…...

多种调度模式下的光储电站经济性最优储能容量配置分析(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

二分法(适用于任何题型!!!)

今天看二分法看了一天,看吐了,现在讲讲怎么做类题。 只讲两种做法(实则是可合并为一种),任何题型都可以转化为这种做法!!!是任何! 首先,设置 int left,righ…...

js常见的七种继承及实现

在 JavaScript 中,常见的继承方式有以下七种:大厂面试题分享 面试题库前后端面试题库 (面试必备) 推荐:★★★★★地址:前端面试题库1. 原型链继承原型链继承是 JavaScript 中一种基于原型的继承方式&#…...

案例分析之——理由Mybatis动态SQL实现复用

无复用思想的做法: 在没有复用思想的时候,就只顾着实现功能。比如开发过程中涉及到两个表的更新功能,每需要更新一处,就写一个接口,结果出现了写了11个接口的情况。 这样虽然功能实现了,可是可能自…...

MCM 箱模型建模方法及大气 O3 来源解析实用干货

OBM 箱模型可用于模拟光化学污染的发生、演变过程,研究臭氧的生成机制和进行敏感性分析,探讨前体物的排放对光化学污染的影响。箱模型通常由化学机理、物理过程、初始条件、输入和输出模块构成,化学机理是其核心部分。MCM (Master Chemical M…...

【独家】华为OD机试 - 最长连续交替方波信号(C 语言解题)

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明本期…...

代码随想录算法训练营第二十一天打卡 | 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

打卡第21天,继续二叉树,前几天终于补完了,感觉难度上来了。 今日任务 530.二叉搜索树的最小绝对差501.二叉搜索树中的众数 二叉树的最近公共祖先 530.二叉搜索树的最小绝对差 给你一个二叉搜索树的根节点 root ,返回 树中任意两不…...

虚拟体验网站/每天三分钟新闻天下事

雪上加霜 本人一名Android程序员,今年29岁了。大厂小厂都呆过,现在在腾讯工作!明明工作顺利,家庭和睦儿女成全,但是总是会感觉到,一股无形的压力,推着我走!作为一名程序员我最怕的不…...

3d打印网站开发/网络营销研究现状文献综述

写在开头: 本文旨在阐述一些大家容易产生迷惑的GCD相关内容,如果是需要了解一些GCD概念或者基础用法,可以看看这两篇文章:GCD 扫盲篇、巧谈GCD 。 目录: 迷惑一:队列和线程的关系 迷惑二:GCD的死…...

团购模板网站/邯郸seo营销

信息存储大多数计算机使用八位的块,或者字节,作为最小的可寻址的内存单位,而不是访问内存中单独的位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存。内存的每个字节都由一个唯一的数字来标识,称为它的地址…...

绍兴公司网站建设/软件外包企业排名

1.高斯消元概念 高斯消元法的本质是行变换,是化系数矩阵A为上三角矩阵。当矩阵A的秩小于未知元个数时,就存在基础解系。 2. 基本性质 2.1 是否要求系数矩阵A必须为方阵? 对于齐次线性方程组,只要考虑系数矩阵A。如果矩阵A是方阵…...

会搭建网站找什么工作室/谷歌seo综合查询

http://blog.csdn.net/smartempire/article/details/23168945 看关于LBP人脸识别的论文时提到了Histogram intersection这个方法,方法最初来自The Pyramid Match Kernel:Discriminative Classification with Sets of Image Features这篇论文,用来对特征构…...

自己如何做简单网站/seo关键词优化的技巧

Linux系统查看文件内容的特殊方法:最基本的有cat和less,more,如果有特殊的要求的话。1/如果只想看文件的前5行,可以使用head命令,如:head -5 /etc/passwd2/如果想查看文件的后10行,可以使用tail命令&#x…...