一、yum 背景知识

1.1、商业生态

我们在安装一个软件之前,需要先下载 对应的软件包,但是这个软件包并不存在于我们本地的计算机磁盘,而是存在于远端服务器上;那么计算机如何知道该软件存在于具体的哪一台服务器上呢?

对于电脑来说,我们一般通过搜索对应软件的官网来得到相应软件包;对于手机来说,表面上我们通过手机自带的应用商店来下载软件包,但实际上应用商店里面并不存在软件包,而只是存在着对应软件官网的链接,最后我们的软件包还是从官网上下载的;

其次,这些软件包是由谁提供的呢?答案很明显,它们是由一些企业、组织或个人提供的;这些企业、组织以及个人为了某种利益编写出了软件包,然后将其放在了对应的服务器上。

自此,一条简单的商业生态链就出来了 – 一部分人编写出了软件包供其他人使用,并通过收费或者内置广告等方式从中获取利益;同时,它们也向手机厂商支付费用,使得自己的软件能够在对应手机的应用商店或者第三方的下载工具 (比如迅雷、应用宝) 中被下载使用。

1.2、开源 生态

有人编写软件是为了赚钱,自然也有的人不为赚钱,他们可能是为了提高技术与获得成就感、也可能是为了提高自己的知名度、又异或是无聊等等原因;总之,有的人会将自己编写出的软件包的源代码公开,让别人能够免费随意使用,这种就叫开源;

在托瓦兹编写出了Linux操作系统并开源之后,世界上有很多人参与到了Linux的完善与扩展中来,其中也不乏为Linux免费编写软件的人;这些人会加入相应的Linux社区,然后将自己编写的软件放在社区对应的服务器上;而不同的社区会在自己的Linux版本中内置服务器和软件对应的下载链接,而这个用于存放下载链接的软件就是yum;

yum (Yellow dog Updater, Modified) 是Linux下非常常用的一种包管理器;主要应用在 Fedora, RedHat,Centos 等发行版上;软件包和软件包管理器, 就好比 “App” 和 “应用商店” 这样的关系。

上面的过程也是开源生态的形成过程 – 不同的Linux发行版创建对应的Linux社区,社区拥有一个公共账户,用于接受来自世界各地的捐款,然后用账户里面的资金购买服务器、举行各种活动等等;来自世界各地的具有开源精神的人将自己编写的开源软件部署在社区的服务器上;社区再将这些软件的下载链接拷贝到对于Linux发行版的软件包管理器 (比如yum) 中,使得我们能够在Linux中通过软件包管理器安装使用各种软件。

1.3、软件生态本土化

由于西方在计算机方面起步与发展比我国要早很多,所以我们上面所说的开源生态最先在西方形成,即大多数Linux社区,包括社区对应的服务器都是部署在国外的;所以在国内通过链接下载软件时访问会比较慢,再加上我国的一些特殊国情,有时候还会访问失败;

针对上面这种情况,我国的一些高校以及公司就 镜像了国外的软件服务,即把国外服务器上的软件拷贝到了国内自己公司的服务器上,使得我们可以直接访问国内的服务器来下载软件;

但是只拷贝软件还不行,因为 yum 中下载软件时默认访问的链接还是国外的,所以这些高校/公司还提供了一套国内的下载链接配置文件 – yum 源配置文件;

在Linux中,yum 源配置文件 是存在于 /etc/yum.repos.d/ 目录下的 CentOS-Base.repo 文件:在这里插入图片描述

如果你使用的是云服务器,那么 yum 源一般都是配置好的,如果你使用的是虚拟机,你需要打开 CentOS-Base.repo 查看里面的链接是否是国内的链接,如果不是,就需要自己手动配置,配置的方法网上很多,直接搜索对应的Linux发行版即可;
在这里插入图片描述

二、yum 的基本使用

2.1、查看软件包

我们可以通过 yum list 命令罗列出当前一共有哪些软件包;但由于包的数目非常之多, 所以我们一般结合管道和grep 命令来筛选出我们关注的包;如:在这里插入图片描述

注意事项

  • 软件包名称构成:主版本号.次版本号.源程序发行号-软件包的发行号.主机平台.cpu架构;
    “x86_64” 后缀表示64位系统的安装包,“i686” 后缀表示32位系统安装包,选择包时要和系统匹配;
  • “el7” 表示操作系统发行版的版本: “el7” 表示的是 centos7/redhat7,“el6” 表示 centos6/redhat6;
  • 最后一列中 base 表示的是 “软件源” 的名称, 类似于 “小米应用商店”, “华为应用商店” 这样的概念;

2.2、安装软件

我们可以通过如下命令来安装软件包 (其中 -y 代表不询问直接安装):

yum install -y 软件名

在这里插入图片描述

有一些软件并没有被纳入 Centos、Ubuntu、Kail等相关生态平台的官方软件集合中,如果我们想使用这些软件,需要安装 非官方软件集合列表 – epel-realse;

注意事项

  • 安装软件时由于需要向系统目录中写入内容,一般需要 sudo 或者切到 root 账户下才能完成;
  • yum安装软件只能一个装完了再装另一个;正在yum安装一个软件的过程中,如果再尝试用yum安装另外一个软件,yum会报错;
  • 软件和软件之间是有关联的,即具有一定的耦合度; yum 为了解决软件之间相互依赖的问题,有时候在安装一个软件会连带安装其他一些软件。

2.3、卸载软件

卸载软件的指令如下 (其中 -y 代表不询问直接卸载):

yum remove -y 软件名

在这里插入图片描述

注意:关于 yum 的所有操作必须保证主机 (虚拟机) 网络畅通;可以通过 ping 指令验证网络:在这里插入图片描述

三、vim 的基本使用

3.1、vim 的基本概念

Vim 被誉为世界上最强大的编辑器,是一个类似于 Vi 的著名的功能强大、高度可定制的 文本编辑器,在Vi的基础上改进和增加了很多特性;vi/vim 都是多模式编辑器,不同的是vim是vi的升级版本,它不仅兼容vi的所有指令,而且还有一些新的特性在里面,例如语法加亮、可视化操作;其不仅可以在终端运行,也可以运行于x window、 mac os、windows。

vim 一共有12中模式,我们目前掌握其中三种模式即可,分别是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能区分如下:

  • 正常/普通/命令模式 (Normal mode)

控制屏幕光标的移动,字符、字或行的删除,移动复制某区段以及进入Insert mode下,或者到 last line mode;

  • 插入模式 (Insert mode)

只有在Insert mode下,才可以做文字输入,按「ESC」键可回到命令行模式,该模式是我们后面用的最频繁的编辑模式;

  • 底行模式 (last line mode)

文件保存或退出,也可以进行文件替换,找字符串,列出行号等操作,在命令模式下,输入 : 即可进入该模式;

我们可以在底行模式下输入 “help vim-modes” 来查看 vim 的所有模式。在这里插入图片描述

3.2、vim 的基本操作

  • 模式间切换
    我们使用 vim 打开一个文件时默认处于命令模式,然后我们可以通过如下指令切换到其他模式:
  • [命令模式]切换至[插入模式]:输入 i/a/o;其中使用 i 进入时光标处于第一个字符之前,使用 a 进入时光标处于第一个字符之后,使用 o 进入时光标处于第一行之后空白行的行首;
  • [命令模式]切换至[末行模式]:「shift + ;」, 其实就是输入「:」;
  • [其他模式]切换至[命令模式]:[Esc];
  • 退出 vim:在底行模式下输入 wq,其中 w 是保存的意思,q 是退出的意思,我们也可以不保存直接退出;

在这里插入图片描述

注意:从其他任意模式切换到命令模式都是 [Esc],只是有的只需要按一次,有的需要按多次,总之无脑 [Esc] 最终一定可以回到命令模式。

  • 光标定位
  1. $ – 将光标移动到行尾;
  2. ^ – 将光标移动到行首;
    1.G – 将光标移动到文件末尾;
  3. gg – 将光标移动到文件开头;
  4. n + G – 将光标移动到第 n 行;
  5. h j k l 将光标向 左 下 上 右 移动;
  • 文本复制
  1. yy – 复制当前行 (nyy:从当前行开始向下复制n行);
  2. p – 粘贴一次 (np:粘贴n次);
  3. dd – 删除当前行 (ndd:从当前行开始向下删除n行);
  4. u – 撤销操作 (后退一步);
  5. ctrl + r:取消撤销操作 (前进一步);

注意:vim 下的所有删除操作都相当于 Windows 下的剪切操作;

  • 文本编辑
  1. ~ – 切换光标所在字符的大小写 (长按~:从光标所在字符开始往后切换所有字符的大小写,直到遇到行尾);
  2. rx – 将光标所在字符替换为x字符 (nrx:将光标所在字符开始往后的n个字符都替换为x字符);
  3. R – 批量化替换,即切换为替换模式,用键盘输入的字符替换光标所在字符,且替换之后光标自动后移,等待替换下一个字符;我们最后需要输入 [Esc] 从替换模式切回命令模式;
  4. x – 删除光标所在字符 (nx:删除光标所在字符开始往后的n个字符);
  5. X – 删除光标所在字符的前一个字符 (nX:删除删除光标所在字符的前n个字符);
  6. w – 将光标跳转到下一个字的第一个字符处 (nw:将光标跳转到下n个字的第一个字符处);
  7. cw – 更改光标所在处的字到字尾处,和 R 一样,此命令会让我们跳转到插入模式 (cnw:更改n个字);
  • 底行模式的操作
    上述操作全部都是在命令模式下进行的,除了命令模式,我们常用的还有插入模式和底行模式,而插入模式基本没有什么快捷操作,所以下面我们最后来学习一些底行模式的基本操作;
  1. set nu – 设置行号 (set nonu:取消行号);
  2. vs – 分屏 (注意:无论我们分几个屏,光标只有一个,它代表我们正在对哪个屏幕进行操作);
  3. ctrl + ww – 切换光标到不同屏幕 (注:此指令在命令模式下执行);
  4. wq – 报存退出,w 代表保存,q 代表退出,二者可以分开单独执行;
  5. wq! – 强制保存并强制退出,w! 代表强制保存,q! 代表强制退出,二者可以分开单独执行;
  6. %s/mark1/mark2/g – 将文本中所有的 mark1 替换为 mark2 (s 代表替换,g 代表全局);
    !指令 – 在不退出 vim 的情况下执行Linux中的各种指令;

四、简单 vim 配置

4.1、配置前提

在目录 /etc/ 下面,我们可以找到有一个名为 vimrc 的文件,这是系统中公共的vim配置文件,对所有用户都有效;在这里插入图片描述
系统默认的vim全局配置文件对vim进行了一些基本配置,比如语法高亮、背景颜色等等,但是还是有许多不方便的地方,比如没有自动缩进、没有括号补齐、没有行号显示等等;在这里插入图片描述

所以我们要对 vim 进行一些其他的基本配置,使得我们能够在便捷的在vim中编写C/C++程序;特别注意:虽然Linux中的所有用户使用的都是同一个vim程序,但是大家使用的是不同的vim配置,因为每个用户的家目录下都会有一个属于自己的 .vimrc 文件,这个文件中保存的就是专属于这个用户的 vim 配置。在这里插入图片描述

4.2、简单 vim 配置

我们可以在网上搜索,从而进行一些vim的基本配置,比如

  • 设置语法高亮: syntax on;
  • 显示行号: set nu;
  • 设置缩进的空格数为4: set shiftwidth=4;

在这里插入图片描述

4.3、一键 vim 配置

由于 vim 的配置选项杂而多,因此我们想要配置出一个便捷好用的 vim 是要花费很多的时间的;所以我在 Gitee 上找了一个 vim 一键配置的方法一键配置
在这里插入图片描述
然后我们输入 “source ~/.bashrc” 或者重启终端即可使 vim 配置失效:在这里插入图片描述

可以看到,配置完成后的 vim 不仅会显示当前模式、文件名、字符个数,还支持自动缩进、自动补齐 (语法、括号、引号等等)在这里插入图片描述
但是这里存在一个小问题:此处的自动缩进默认是两个字符,而我们编写C/C++程序时一般都要求缩进四个字符,所以我们需要打开 .vimrc 文件对默认缩进进行修改:在这里插入图片描述
在这里插入图片描述
至此,我们的 vim 一键配置就完成了。(注:安装 vimforcpp 时产生的各种隐藏文件,比如 .VimForCpp .vim 一定不能删;产生的非隐藏文件 – install.sh 可以删除,但是也建议不要删)

五、配置 sudo 权限

在学习 文件权限 的时候我们提到可以用 sudo 指令来对普通用户进行提权,从而使得普通用户可以以root用户的身份去执行指令,但是前提是该用户必须是受信任的用户,即该用户必须处于 etc/sudoers 文件中;在这里插入图片描述

学习了 vim 的使用之后,我们就可以在 root 下将自己添加进 sudoers 文件中了:在这里插入图片描述
在这里插入图片描述
现在,我们就可以在普通用户下使用 sudo 对指令进行提权了在这里插入图片描述

六、Linux编译器 - gcc/g++ 使用

6.1、引言

在C语言 程序员内功心法之程序环境和预处理 博文中,我们就学习到 – 一个程序要被运行起来需要经历四个阶段:预处理 (预编译)、编译、汇编、链接 ,下面我们来简单回顾一下这四个阶段会进行的操作。

6.2、预处理

预处理也叫预编译,程序在预处理阶段会完成如下操作:

  • 注释的删除。
  • #define 定义的符号、宏的替换以及删除。
  • 条件编译的执行。
  • 头文件的包含:将头文件中的代码拷贝到当前代码中来。
  • 在Linux下我们可以通过如下命令来得到预处理之后的代码:
gcc -E test.c -o test.i
# gcc:表示用 gcc 编译器来编译此代码
# -E:表示让代码在完成预处理后停下来,不再继续往后编译
# test.c:我们要编译的代码
# test.i 预处理产生的文件一般以.i为后缀
# -o test.i:用于指明临时文件的名称(test.i),它会将预处理之后的代码保存到指明的临时文件中,而不是直接打印到终端上

具体我们后面系统学可以先看

//测试案例 -- test.c
#include <stdio.h>

#define M 1024

int main()
{
    //测试注释
    //printf("hello 1\n");
    //printf("hello 2\n");
    //printf("hello 3\n");
    
    printf("hello 4\n");
    printf("hello 5\n");
    printf("hello 6\n");
    printf("hello 7\n");
    
    //测试宏    
    printf("%d\n", M);
    
    //测试条件编译    
#ifdef SHOW                                                                                                                       
    printf("hello SHOW\n");    
#else    
    printf("hello DEFAULT\n");    
#endif    
    
    return 0;    
}    

在这里插入图片描述
在这里插入图片描述

可以看到,预处理后 stdio.h 里面的内容会被拷贝到 test.i 里面,所以 test.i 一共有800多行;同时,预处理阶段也完成了我们上述提到的其他工作。

6.2、编译

程序在编译阶段会完成如下操作:

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

在Linux下我们可以通过如下命令来得到编译之后的代码:

gcc -S test.i -o test.s      
# -S:表示让代码在完成编译后停下来,不再继续往后编译
# 编译产生的文件一般以.s为后缀

在这里插入图片描述

在这里插入图片描述
可以看到,编译阶段会将高级语言转换为汇编语言(有点像vs的反汇编)。

6.3、汇编

汇编阶段是把编译阶段生成汇编代码转成计算机可以识别的二进制目标代码,其中生成的 .o 文件被称为可重定向二进制目标文件。

在Linux下我们可以通过如下命令来得到编译之后的代码:

gcc -c test.s -o test.o  
# -c:表示让代码在完成编译后停下来,不再继续往后编译
# 汇编产生的文件一般以.o为后缀

在这里插入图片描述
在这里插入图片描述
如上,汇编得到的二进制目标文件使用一般的文本编辑器打开时是一堆我们看不懂的符号 (与符号的编码有关 – utf-8)

我们可以使用 od 指令以指定格式来打开它 (默认是以八进制打开)。在这里插入图片描述

6.4、链接

程序在链接阶段会完成如下操作:

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

在Linux中,链接我们直接使用 gcc 即可,没有额外选项,因为链接是程序的最后一个阶段;同时,链接的结果默认存放在 a.out 中。

gcc test.o -o test.out

在这里插入图片描述

链接得到的文件被称为可执行程序,它里面存放的也是计算机能够识别的二进制指令。在这里插入图片描述
注:gcc 预处理编译链接三个阶段对应的选项和文件后缀有一个记忆技巧 – ESc 与 iso,其中 ESc 分别代表 -E -S -c,iso 分别代表 .i,.s,.o;ESc 可以对比电脑上的 [Esc] 键,将其中的 s 改为大写即可;iso 就是系统镜像

同时,我们此处将 gcc 编译代码分为预处理、编译、汇编、链接四个阶段是为了让大家更深层次的理解一个程序的运行过程;日常编译代码的时候直接使用 “gcc test.c -o test.out” 或 “gcc test.c” 编译源文件得到可执行程序即可。

七、链接方式与函数库

7.1、 动态链接与静态链接

我们在编写代码的时候,除了自己实现函数之外,我们还会去调用函数库中的代码,比如 scanf/printf/malloc/fopen;但是我们要明白,库中的代码是别人给我们写好供我们直接使用的,即我们只有该函数的调用,而没有函数的实现;

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

  • 程序一共有两种链接方式:动态链接与静态链接;
  • 动态链接是指执行代码时,如果遇到库函数调用就跳转到动态库中对应函数的定义处,然后执行该函数,执行完毕后再跳转回原程序并继续往下执行;它的优点是形成的可执行程序小,缺点是受到动态库变动 (删除、升级等) 的影响。
  • 静态链接则是直接将本程序内部要使用的库函数从对应的静态库中拷贝一份过来;它的优点是不与静态库产生关联,即不受静态库变动 (删除、升级等) 的影响;缺点是形成的可执行程序非常大。

7.2、 动态库与静态库

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

  • 静态库是指编译链接时,把需要的库文件代码全部拷贝到可执行文件中,因此生成的文件非常大,但在运行时也就不再需要库文件了,在Linux下其后缀名为 “.a”,在Windows下其后缀名为 “.lib”;
  • 动态库也被称为共享库,它与静态库相反,在编译链接时并没有把相应的库文件代码加入到可执行文件中,而是在程序执行时由运行时链接文件来加载库,这样可以节省系统的开销,在Linux下其后缀名为 “.so”,在Windows下其后缀名为 “.dll”;
  • 库分为动态库和静态库,库有自己的命名风格,libname.so.xxx或libname.a.xxx这中间对应文件的name区域那么即为库的名,其中xxx为库的不同版本,例如c语言中的库name对应就为c,那么就为c标准库

注:动态链接必须使用动态库,静态链接必须使用静态库;即进行动态链接时只能跳转到动态库中对应函数的实现处,进行静态链接时只能拷贝静态库中的函数。

Linux中默认使用动态库进行动态链接,原因如下:

  • 程序形成的可执行程序大不仅仅是占用的磁盘空间大,其被运行时加载到内存所占用的内存空间也会非常大,而目前我们使用的机器的内存基本上都是8/16GB的,所以运行不了过大的可执行程序;
  • 虽然动态链接受函数库变动的影响,但是函数库一般很少会变动,即使变动也必须兼容以前的版本,所以影响不大;

在Linux下,我们可以使用 “file” 指令来辨识文件类型,使用 “ldd” 来打印或者查看程序运行所需的共享库。
在这里插入图片描述
在这里插入图片描述
Linux 一般都会自动安装C语言动态库,因为Linux下的大多数指令以及我们默认使用 gcc 编译得到的可执行程序都是进行动态链接,依赖C动态库的;但是C静态库、C++静态库可能就需要我们自己安装了。

我们可以使用如下命令来安装C和C++静态库(因为涉及在系统位置安装要加sudo):在这里插入图片描述
我们也可以在gcc使用 “-static” 选项来指定程序使用静态方式来进行链接:

gcc test.c -o test.exe -static

在这里插入图片描述
在这里插入图片描述
可以看到,以静态链接方式形成的可执行程序比动态链接形成的要大100~200倍,即一个动态链接只有100M的文件,静态链接就会变成十几个G,二者之间相差非常大。

八、gcc/g++ 的使用

8.1、gcc/g++ 的安装

其实上面在学习预处理、编译、汇编、链接时我们就已经在使用 gcc/g++ 了,只是比较零散,下面我们来系统的学习一下 gcc/g++。

在Linux下,我们可以使用如下指令来安装 gcc 与 g++:

sudo yum install -y gcc
yum install -y gcc-c++ libstdc++-devel

8.2、gcc/g++ 的使用

gcc 和 g++ 的使用方法非常类似,因为他们的选项基本都是一样的:

  • -E 在完成预处理后停下来,不再继续往后编译,生成的文件以 .i 为后缀;
  • -S 在完成编译后停下来,不再继续往后编译,生成的文件以 .s 为后缀;
  • -c 在完成汇编后停下来,不再继续往后编译,生成的文件以 .o 为后缀;
  • -o 将输出到终端的内容保存到指定文件中;
  • -static 对生成的文件采用静态链接;
  • -g 以debug方式发布软件,即生成调试信息,GNU 调试器可利用该信息;
  • -shared 尽量使用动态库,需要系统存在动态库;

在这里插入图片描述

九、Linux调试器 - gdb 使用

9.1、debug 和 release

在Windows中使用VS的时候我们知道:程序的发布方式一共有两种 – debug 模式和 release 模式;其中 debug 模式是给程序员用的,其中包含调试信息,程序员可以根据这些调试信息对程序进行修改与完善;而 release 模式则是给用户用的,它不包含调试信息,因为用户不负责也不关心如何对程序进行调试。

Linux 中使用 gcc/g++ 编译链接得到的程序默认是 release 模式的,如果我们要使用 gdb 进行调试,必须在源代码生成二进制程序的时候添加 -g 选项;

//测试代码
#include <stdio.h>

int Add(int begin, int end)
{
    int ret  = 0;
    int i = 0;
    for(i=begin; i<=end; ++i)
    {
        ret += i;
    }
    return ret;
}


int Fac(int x)
{
    int ret = 1;
    int i = 0;
    for(i=1; i<=x; ++i)
    {
        ret *= i;
    }
    return ret;
}

int main()                                                                                                                                                                                  
{
    int a = 0;
    int b = 100;

    int add = Add(a, b);
    printf("ret = %d\n", add);
    printf("ret = %d\n", add);
    printf("ret = %d\n", add);

    int fac = Fac(10);
    printf("fac = %d\n", fac);
    printf("fac = %d\n", fac);
    printf("fac = %d\n", fac);
    return 0;
}

在这里插入图片描述
这个指令可以查看debug信息

readelf -S test.exe | grep debug

在这里插入图片描述
可以看到,以 debug 和 release 模式发布的程序无论是在程序大小、程序内部包含的有关调试的二进制信息,还是 gdb 模式下是否具有调试样例都是有明显区别的。

9.2、gdb 的安装

在Linux下,我们可以使用如下命令来安装 gdb:

sudo yum install -y gdb

在这里插入图片描述

9.3、gdb 的使用

gdb 调试的常见选项如下:

  • l 行号:从指定的行号开始往下显示源代码,每次显示10行 (l – list);(注:gdb 有自动记忆命令的功能,即当我们第一次使用 l 显示源代码后,我们下一次再使用 l 或者下一次按下 enter 键时,它会接着上次的位置往下显示)
    l 函数:列出某个函数的源代码 (l – list);
    r:运行程序 (r – run);
    b 行号:在某一行打一个断点,相当于VS中的F9 (b – breakpoint);
    info b:查看断点;
    d 断点编号:删除断点 (d – delete);(注:每个断点都有自己的编号,我们删除断点时需要指明对应的断点编号)
    r:调试运行,如果程序中有断点,则在断点处停下来,如果没有,则直接将程序跑完,相当于VS中的F5 (r – run);
    n:逐过程调试,相当于VS中的F10 (n – next);
    s:逐语句调试,相当于VS中的F11 (s – step);
    c:运行至下一个断点处停下 (c – continue);(注:如果断点所在行不是一条语句,比如 “{” “}” 或者 空行,那么它会继续往下到有效行处停下 )
    bt:查看调用堆栈 (breaktrace);
    p 变量:查看变量值 (p – print);
    display/undisplay 变量:跟踪查看一个变量,每次停下来都显示它的值,undisplay 取消对先前设置的那些变量的跟踪;
    finish:把当前函数运行完;
    disable breakpoints:禁用断点;
    enable breakpoints:启用断点;
    quit:退出 gdb;
  • 启动gdb
    gdb 可执行文件名

观察到如下场景即为我们的gdb调试器启动成功,那么接下来我们将在(gdb)命令行中输入调试命令进行我们程序的调试

在这里插入图片描述

  • 退出
    q

退出

在这里插入图片描述- 查看行号对应10行代码

l n

n代表你所要查看行号,即可显示该行号对应代码,如果输入的行号为1,那么会从第1行开始显示共计10行代码,如果该行号为一个中间的行号,那么会居中显示该行号,并且显示该行号上5行,下5行,共计10行代码
gdb会默认记住命令,如果你输入命令后,下一次输入默认继续执行上一次的命令,并且如果你查看的是行号会继续从上一次查看的最后一行的位置继续向下查看

在这里插入图片描述

  • 查看函数代码
    l 函数名

查看函数

在这里插入图片描述

  • 运行程序

r ,可以运行程序,如果没有设置断点,那么默认执行到程序的最后,如果设置了断点,那么默认运行到第一个断点的位置在这里插入图片描述

  • 设置断点

b n

n代表行号,在某一行设置断点

b 函数名

在函数的开头设置断点

b 源文件: n

在源文件行号为n的位置处设置断点

在这里插入图片描述

  • 查看断点

info b

可以查看断点的信息,并且根据断点设置的时间先后标序号

在这里插入图片描述

  • 删除断点

d n

这个n代表断点的序号,例如下图中的Nnm那一行代表的序号

d breakpoints

可以删除所有断点

在这里插入图片描述

  • 禁用断点和启用断点

disable n

这个n代表断点的序号,禁用断点

enable n

这个n代表断点的序号,启动断点

在这里插入图片描述

  • 逐过程调试和逐语句调试

这里的调试过程一定是r先运行起来才能进行逐过程调试或逐语句调试
n(next)

逐过程调试,类似于vs中的F10,不会进入函数

s(步长)

逐语句调试,类似于vs中的F11,会进入函数

在这里插入图片描述

  • 打印变量值

p 变量

调试运行起来,可以进行打印变量对应的值(这里的作用仅仅是打印,无其它作用)

在这里插入图片描述

  • 跟踪变量(让变量每次停下来都显示)

display 变量名

跟踪查看一个变量,每次停下来都显示它的值,类似于vs中的监视窗口监视变量的作用

在这里插入图片描述

  • 取消追踪变量

undisplay

可以取消对所有变量的追踪(这里不可以单独取消对某个变量的追踪,要取消只能统一取消对全部变量的追踪)

在这里插入图片描述

  • 查看当前局部变量的值

info locals

可以查看当前局部变量的值

在这里插入图片描述

  • 设置局部变量的值
    set var 变量名=你要给变量设置的值

比如循环前50次没有问题,你想快速跳转至第51次有没有问题,可以使用修改循环变量的值达到快速跳转进行调试

在这里插入图片描述

  • 执行到函数返回

finish

可以指向到当前函数的返回,并且停在函数调用的那个位置

在这里插入图片描述

  • 跳到下个断点

c

跳转到下一个断点

在这里插入图片描述

  • 跳转到指定行

until n

n代表行号,跳转到指向行n

在这里插入图片描述

  • 查看函数调用堆栈
    bt

查看函数调用堆栈(即各级函数调用及其参数)

在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐