Linux相关工具vim/gcc/g++/gdb/cgdb的使用详解
目录
Linux开发工具vim
什么是vim?
vim的操作使用
命令模式常见命令
底行模式常见命令
vim配置
Linux编译器-gcc/g++使用
什么是gcc/g++?
gcc编译流程
gcc常见选项
动态链接和静态链接
动态库与静态库
Linux调试工具-gdb/cgdb
什么是gdb?
debug和realease
gdb的使用
相关调试命令
总结:
Linux开发工具vim
什么是vim?
Vim 是一款跨平台、开源的轻量级文本编辑器,核心特点是“以键盘快捷键为核心操作逻辑”,不依赖图形化界面(也有图形化版本,但非主流),能在终端/命令行中直接运行,广泛用于代码编写、文本修改等场景,尤其在 Linux/macOS 生态中极为常用。
通俗点来说vim是一款编辑器,平时大家是怎么编写代码的呢?怎么编译代码呢?debug代码呢?vim可以满足多种应用场景,它类似于windows下的集成开发工具vs2022
Linux当中是用vim编辑器来编写代码的,gcc/g++编译器用来编译代码,gdb调试器用来调试代码,这些都是独立的工具,而windows下的vs2019是集成开发工具
vim的操作使用
vim是什么呢?文件编辑器,可以用来编写代码
那么怎么使用vim呢?
vim test.c
当test.c存在时,就可以直接在文件里面写代码;
当test.c不存在时,就会重新新建一个test.c文件,并在里面编写代码
- vim是一个多模式编辑器
这是 vim 最核心、也是新手入门最难的地方——它不像记事本那样“打开就能输入”,而是分为 3 种核心模式,不同模式下键盘按键的功能完全不同,目的是通过“模式切换”减少鼠标操作,提升编辑效率
- vim的模式
命令模式(默认打开是命令模式)
插入(编辑)模式(使用最频繁)
底行模式
- 普通模式(Normal Mode):打开 vim 后的默认模式,不能直接输入文字,核心用于“移动光标”“快速操作”(比如复制一行、删除一段、替换字符)。
- 插入模式(Insert Mode):只有进入这个模式,才能像记事本一样输入文字。从普通模式按“i”(在光标前插入)、“a”(在光标后插入)就能切换进来,按“Esc”键可退回普通模式。不过有⼀点要特别注意,进入vim之后,是处于[命令模式],你要切换到[插⼊模式]才能够输入文字。
- 命令模式(Command Mode):用于执行“全局操作”,比如保存文件、退出 vim、查找文字。从普通模式按“:”(冒号)就能进入,输入“w”表示保存,输入“q”表示退出,输入“wq”表示保存并退出。
三种模式如何切换?
任何模式回到命令模式,都可以按Esc,插入模式进入底行模式,首先需要回到命令模式(Esc),然后 shift+:就可以了;底行模式进入命令模式:按Esc就直接回到命令模式;底行模式进入插入模式:按Esc进入命令模式,然后 i 进入插入模式
命令模式常见命令
复制与粘贴
- yy:复制当前行
- p:粘贴,光标在哪里就粘贴到下一行
- np:n代表想要粘贴n次
将光标放在所要复制的该行,然后输入yy,此时已经复制了,光标放在想要粘贴到的行数的前一行,然后再输入p就粘贴了;光标在哪里,就粘贴在光标所在行的下一行
上面是复制行,那么有没有多行复制的命令呢?有的:
- nyy:n代表从光标开始想要复制几行
那么我们误复制粘贴了怎么办?
- u:撤销上次动作
- ctrl+r : 撤销刚刚的撤销,相当于是反撤销
- dd:删除光标所在行,其实功能更像剪切
- ndd:删除光标所在行开始的n行内容
文本修改替换删除
- r : 替换光标所在处的字符。
- nr : 一次批量化的从光标开始连续替换内容
- shift+r:进入替换模式,整体文本替换
esc回到命令模式
- shift + ~:批量化进行大小写转化
- x,nx:删除光标所在文本的内容,从左到右
- shift+x:删除光标所在文本的内容,从右到左
光标定位
- h,j,k,l:左,下,上,右
为什么我们的键盘有上下左右键还用hjkl这样的按键呢?因为早期的键盘是没有上下左右键的,
记忆:h(最左边),j(jump跳楼),k(king高高在上),l(最右边)
- w:以单词为单位进行后移
- b:以单词为单位进行前移
- nb,nw:按照n个单词进行前移或者后移
- shift+4($):将光标定位到当前行的最结尾
- shift+6(^):将光标定位到当前行的最开始
- gg:直接将光标定位到文件的最开始
- shift+g:直接将光标定位到文件的最后
- n+shift+g:将光标定位到任意第n行
注释命令
单行注释
- 对于 // 类注释(C、C++、Java 等):将光标移到目标行,输入 I//<Esc> 。
多行注释(批量注释)
- 1. 按 Ctrl+v 进入可视块模式;
- 2. 移动光标( j / k 键)选中需要注释的多行;
- 3. 输入 I#<Esc> (或 I//<Esc> ,根据语言选择注释符号),即可为选中的所有行在行首插入注释符号。
底行模式常见命令
- :s/old/new :替换当前行中第一个 old (旧内容)为 new (新内容)
- :s/old/new/g :替换当前行中所有 old 为 new (“g” 表示“global”全局)
- :%s/old/new/g :替换整个文件中所有 old 为 new (“%” 表示整个文件)
- :%s/old/new/gc :替换整个文件中 old 为 new ,且每次替换前询问确认(“c” 表示“confirm”确认)
举个例子:
如果我们想将printf全部替换为cout , 就可以使用命令 :%s/prntf/cout/
- :w :保存当前文件(“write” 缩写)
- :q :退出当前Vim窗口(“quit” 缩写,需确保文件已保存)
- :wq :保存文件并退出Vim窗口(常用组合)
以上命令全部加! , 分别表示强制保存,强制退出,强制保存并退出
- set nu : 输入 set nu 后,会在文件中的每一行前面列出行号。
- # : #号表示一个数字,在冒号后输入一个数字,再按回车键就会跳到该行了,如输入数字 15,再回车,就会跳到文章的第15行。
- / : 先按 / 键,再输入想寻找的字符,如果第⼀次找的关键字不是您想要的,可以一直按 n 会往后寻找到要的关键字为⽌。
- ? :先按 ? 键,再输入想寻找的字符,如果第⼀次找的关键字不是想要的,可以一直按 n 会往前寻找到您要的关键字为⽌。
vs : 分屏操作文件,光标在哪里,我们就编辑那个文件
多文件光标切换
ctrl+w,再按h或者l
ctrl+快速两次w
补充内容:
- vim 文件名 +n : 进入文件光标定位在第n行,如果你在编译你的代码时,出错了,然后告诉你出错在第几行,此时你就可以直接今天文件将光标定位在出错附vim近
- !vim : 执行vim上次的命令
- shift+zz : 保存退出 , 和!wq一样
vim配置
为什么要配置Vim?
Vim的默认设置是“最小化通用版本”,很多高频需求没开启,配置的核心目的是解决默认痛点、提升编辑效率,比如:
- 默认没有行号,找代码位置要逐行数,配置后能显示行号;
- 默认Tab键是8个字符宽(代码缩进太宽),配置后可改成4个/2个字符,适配不同语言;
- 默认不支持鼠标操作,配置后鼠标能在Vim里定位、选内容,和普通编辑器一致;
- 默认没有语法高亮、代码折叠,配置后能区分代码关键词、折叠冗余代码,读代码更清晰。
vim的配置全靠一个文件: ~/.vimrc : 我们配置vim需要在一个.vimrc的文件里配置,而在每个用户的主目录下,都可以自己建立私有的配置文件,命名为:“.vimrc”。例如,/root目录下,通常已经存在一个.vimrc文件。
vim的环境设置参数
关于环境设置参数还有很多,这里就不一一说明了。
Linux编译器-gcc/g++使用
什么是gcc/g++?
gcc 和 g++ 不只是“单一的编译工具”,它们本质是“编译工具链”的前端入口,能串联“预处理、编译、汇编、链接”4个核心步骤,从源代码直接生成最终的可执行文件(或库文件),相当于“一站式处理”代码到可执行文件的全流程。
- g++ 是“专属 C++ 的”:专门用来编译 C++ 代码(.cpp 文件),能自动处理 C++ 的类、模板,还会默认加载 C++ 标准库,不用额外配置。
- gcc 不只是“C 语言的”:它能编译 C 代码(.c 文件),也能编译 C++ 代码,但编译 C++ 时要手动加参数加载库,不如g++ 方便,日常更常用它处理 C 语言。
一个C/C++程序从源代码到可执行程序的编译过程:
- 预处理:1、头文件展开 2、宏替换 3、条件编译 4、去注释
- 编译:将C语言转换为汇编语言
- 汇编:汇编语言转换为目标文件(.o,二进制)
- 链接:形成可执行程序
gcc编译流程
这张图片展示了Linux下gcc编译器的使用流程及编译原理
预处理
gcc -E test.c -o test.i
预处理阶段完成头文件的展开、宏的替换、条件编译以及去除注释,选项 -E 是指预处理完成后停止(生成.i文件),不进行编译,-o选项是将生成的文件输出到test.i文件中
编译
gcc -S test.c -o test.s
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。而-S选项的意思就是编译完成后停止(生成.s文件),不进行汇编
汇编
gcc -c test.c -o test.o
汇编阶段是把编译阶段生成的“.s”文件转成目标文件,-c选项就可以看到生成的目标文件
链接
gcc test.o -o myexe
在编译阶段过后,就来到了链接阶段,gcc不带选项就是前面的这些工作依次完成,然后再进行链接生成可执行程序
gcc常见选项
动态链接和静态链接
链接分为动态链接和静态链接
动态链接:
#include<stdio.h>
#define M 100
int main()
{int i = 0;int sum = 0;for(;i<10;i++){sum+=i;}printf("sum=%d\n",sum);while(i>0){i--;}return 0;
}
比如我们写了这么一段代码,求完一到十的累加后,去库里面去找printf函数使用printf函数,使用完之后继续进行我们下面写的代码,我们生成的可执行程序只包含我们自己写的代码以及我们要使用的外部函数的链接,这就是动态链接
静态链接:
对于上面的代码,我们使用printf函数需要去外部的库里面去找,而静态链接相当于就是将printf函数的代码拷贝到我们的代码里面使用,就不用去外部库里面找了
静态链接本质就算将相关库中的代码拷贝到自己的可执行程序里面
查看可执行程序的信息:
ldd 可执行程序名称
仅作用于动态链接的可执行文件或动态链接库(.so 文件),列出其运行时必须加载的所有动态库及库的路径。用于打印程序或者库文件所依赖的共享库列表。
file 可执行程序名称
file命令用于辨识文件类型。通过file指令,我们得以辨识该文件的类型。通过分析文件头部信息,精准判断文件类型,而非仅看文件名后缀
动态库与静态库
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为 “.a”
- 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为 “.so”,如前面所述的libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。
- gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证。
.so:动态库
dynamically linked表示动态链接 .so表示动态库 gcc在编译时默认使用动态库
.a:静态库
g++ -static test.cpp -o test_static
这是用 g++ 以静态链接方式编译 test.cpp 源文件,生成可执行文件 test_static 。其中 -static 参数是关键,它强制编译器将所有依赖的库代码“打包”进最终程序,使其成为静态链接的可执行文件。
用 file 命令查看 test_static 文件的类型。输出中的 statically linked 明确表明该程序是静态链接的,同时还显示了程序的架构(x86-64)、格式(ELF 64位)等信息,验证了前面静态编译的结果。
注意:
Linux下,动态库XXX.so, 静态库XXX.a
Windows下,动态库XXX.dll, 静态库XXX.lib
动态链接和静态链接的优缺点
静态链接的优缺点
优点:
- 移植性强:可执行文件包含所有依赖的库代码,复制到其他相同系统环境的机器上就能直接运行,无需担心依赖库缺失问题。
- 运行时无外部依赖:程序运行时不需要依赖系统中的动态链接库,避免了因动态库版本不兼容或缺失导致的程序崩溃。
缺点:
- 文件体积大:因为把所有依赖的库代码都打包进了可执行文件,所以文件尺寸通常很大,会占用更多的磁盘空间。
- 内存占用高:如果多个程序都使用了相同的静态库,每个程序都会在内存中加载一份库代码,造成内存的重复占用。
- 更新不便:当依赖的库有更新(比如修复了漏洞或增加了新功能),必须重新编译整个程序才能使用新的库版本。
动态链接的优缺点
优点:
- 文件体积小:可执行文件只包含自身的代码和对动态链接库的引用,所以文件尺寸较小,节省磁盘空间。
- 内存共享:多个程序可以共享同一份动态链接库在内存中的加载实例,大大节省了内存资源,例如多个应用程序共享系统的C标准库 libc.so 。
- 更新方便:当动态链接库更新时,只需要替换对应的动态库文件,所有依赖它的程序无需重新编译,就能直接使用新的库功能或修复,比如系统更新了某个图形库,所有依赖该图形库的应用程序都能直接受益。
- 编译速度快:编译时只需要处理自身的代码,不需要把库代码都整合进来,所以编译过程更快。
缺点:
- 移植性差:程序运行时依赖系统中的动态链接库,若目标机器上缺少对应的动态库或库版本不兼容,程序就无法运行,比如在Windows上开发的依赖 xxx.dll 的程序,复制到另一台没有该 dll 的Windows机器上就无法运行。
- 运行时可能出现依赖问题:如果系统中的动态库被错误修改或删除,会导致所有依赖它的程序都无法正常运行。
简单点说 , 静态链接缺点是生成的代码体积大,但是稳定;动态链接优点是生成的代码体积小,但是它依赖第三方库,如果第三方库找不到了,它就会发生错误,我们查看可执行程序文件的属性:
可以看到使用动态链接的可执行程序大小比使用静态链接的可执行程序大小要小
有一个问题:
在编译阶段为什么不直接把C语言代码直接变成二进制代码呢?而是先将C语言代码变成汇编语言,然后将汇编语言变成二进制代码呢?
最早期人们编程是电路开关,01指代,再往后就有了汇编语言,从开始有了汇编以后,计算机就有了编译器这个概念,没有C语言时,只有汇编语言和汇编语言编译器时,那时是汇编语言可以直接会翻译成二进制代码,在有了C语言时,把C语言变成二进制代码要比汇编语言变成二进制成本要高的多,为什么呢?因为C语言是接近于人的自然语言,如果直接把这个语言翻译成二进制,翻译成本是非常高的,所以我们只需要将C语言翻译成汇编语言,而汇编语言翻译成二进制代码这部分工作前人已经帮我们做过了,我们不需要做这部分工作,所以我们只需要管将C语言转换为汇编语言即可,成本大大降低,所以就遵守了这个规则,就有了去注释、编译、汇编、链接
Linux几乎可以直接在命令行中执行大部分后端语言:python,java等等,都可以在Linux当中写代码
Linux调试工具-gdb/cgdb
什么是gdb?
gdb 是 GNU Debugger 的缩写,是 Linux/Unix 系统下最常用的命令行调试工具,核心作用是帮开发者定位程序(如 C/C++ 程序)中的漏洞(如崩溃、逻辑错误、内存泄漏等),能一步步跟踪程序执行过程。相当于linux中的调试器
cgdb 是在 gdb 基础上开发的可视化增强工具,核心功能完全兼容 gdb(所有 gdb 命令都能直接用),最大优势是增加了“源代码窗口”,能实时关联代码与调试过程,不用频繁手动查看代码,比纯命令行的 gdb 更直观。
背景
- 程序的发布方式有两种,debug模式和release模式,Linux gcc/g++出来的二进制程序,默认是release模式,不能调试。
- 在Linux中,程序默认编译的时候采用动态链接,使用动态库,默认生成的可执行程序是:release版本的!是不可被调试的,当需要调试时 :选项-g 表示发布程序以debug方式才可以被gdb调试:
gcc test.c -o test_debug -g
这条指令就是用 gcc 编译器将 test.c 源文件编译成名为 test_debug 的可执行文件,并嵌入调试信息,以便后续用 gdb 等工具调试。
debug和realease
一个可以调试,一个不可以
debug在生成程序的时候,会加入调试信息,而release不会
readelf指令用来显示一个或者多个elf格式的目标文件的信息,这里我们用readelf来显示一下debug版本的可执行程序和release版本的可执行程序,我们发现debug版本中有调试信息,而release版本中没有调试信息
在软件开发中,真正的用户是不需要进行调试的,他们只需要使用软件,所以用户用的版本就不应该将调试信息带进去,而程序员就需要进行调试,所以在程序员端有两种模式:debug版本和release版本
gdb的使用
首先我们先生成debug版本的可执行程序:
gcc test.c -o test_debug -g
进入gdb
gdb test_debug
此时就是进入了
退出gdb
ctrl + d 或 quit
可以看到已经退出了
相关调试命令
list/l 行号 //显示binFile源代码,接着上次的位置往下列,每次列10行。
list/l 函数名 //列出某个函数的源代码。
- watch : watch 命令是调试中“主动监控数据变化”的核心命令,核心作用是给变量或表达式设置“监控点”,当监控的内容(变量值、表达式结果)发生修改时,程序会自动暂停,帮你精准捕捉“谁修改了数据、什么时候修改的”,尤其适合排查“变量被意外篡改”“数据异常变化”等问题。
- set var : set var 命令的核心作用是在调试过程中,手动修改程序中变量(或结构体成员、数组元素)的值,无需重新编译代码,就能快速验证“不同变量值对程序逻辑的影响”,比如模拟边界值、跳过异常分支、修复临时数据错误,大幅提升调试效率。它的本质是“在内存层面修改变量对应的存储数据”,修改后程序会基于新值继续执行,是调试中“主动干预程序流程”的关键命令。
- 条件断点 : 条件断点是在“普通断点(按位置暂停)”基础上,增加了“触发条件”的断点——只有当预设的条件成立时,程序才会在指定位置暂停;条件不成立时,程序会直接跳过该断点继续执行,能避免“频繁暂停无关代码”,大幅提升调试效率,尤其适合循环、分支中的精准调试(如只看循环第100次的执行状态)。
总结:
Vim是一款跨平台的轻量级文本编辑器,以键盘操作为核心,支持多模式编辑(命令/插入/底行模式),是Linux开发的重要工具。GCC/G++是Linux下的编译器,支持预处理、编译、汇编和链接四步编译流程,可生成动态或静态链接的可执行文件。GDB是调试工具,需配合-g选项生成的debug版本程序使用,支持断点设置、变量监控等调试功能。这三种工具共同构成了Linux下C/C++开发的完整工具链。