0


╭(⊙o⊙)ノ★Vim Gcc Gdb★Linux开发三大件熟练指南

基础开发

Windows 下有例如 Visual Studio、IDEA 这样的集编写代码、编译代码、调试代码、运行代码、代码关系维护以及各种各样的复杂功能于一身的开发工具,叫做集成开发环境 IDE。Linux 下一般使用代码编辑工具 vi/vim,编译工具 gcc/g++,调试工具 gdb。

1. 编辑工具 vim

Linux 下编写代码使用 vi/vim,它是一款多模式的十分强大的文本编辑器,所有的类 unix 系统都会内置 vi 编辑器,目前使用较多的是 vim 编辑器,也就是 vi 的升级版。虽说 vim 是个文本编辑器,但它更专注于代码的编写,具有语法高亮等功能。

$ vim fileName

输入上述命令即可将使用 vim 打开文件,文件不存在则会创建文件。

1.1 vim 的基本模式

vim 基本的模式有三:命令模式(normal mode)插入模式(insert mode)底行模式(command mode),vim 刚启动时,就进入命令模式。

  • 命令模式下输入i可以进入输入模式,再按Esc键就可以回退到命令模式。
  • 命令模式下输入:即可进入底行模式,再按Esc键就可以回退到命令模式。
  • 底行模式下输入wq可以保存退出。

知悉上述基本的模式切换方法后,再逐个介绍模式。

命令模式(normal)

vim 刚启动时,就进入命令模式。此状态下敲击键盘动作会被 Vim 识别为命令,而非输入字符。可进行的操作有:控制光标移动,字符、单词或行的删改,移动或复制粘贴文本内容,切换到插入或底行模式。

底行模式(command)

命令模式只有一些最基本的命令,因此仍要依靠底线命令模式输入更多命令。命令模式下输入

:

即可进入底行模式,底线命令模式可以输入多个字符的命令,可用的命令非常多。

插入模式(insert)

文本编辑模式。一般要先退回到命令模式才能进到底行模式。

vim 总共有13种模式,但这三个基本模式已经能满足我们大部分需求,其他模式会在之后的使用中学习。

1.2 vim 正常模式命令集

切换模式
  1. 切换到插入模式i,a,o或底行模式Esc
  2. i选项是从光标的位置开始输入,a选项会将光标向后移动一位,o选项在光标的下方另起一行。
  3. Esc退回到命令模式后向前移动一位。
光标移动
  1. H、⬇J、⬆K、➡L,相当于方向键。
  2. 光标锚点跳至行首^、行尾$;跳至文章起始gg、末尾G;跳至指定行n+gg/n+G
  3. 移动到下一个单词的起始w,移动到下一个单词的末尾e,反向单词距移动b,字符、字母、字母数字组合都被视为单词。
  4. Ctrl+B光标向下翻页,Ctrl+F向上翻页;Ctrl+U向下移动半页,Ctrl+D向上移动半页。
删改内容
  1. 删除当前字符x,多个字符n+x;反向删除字符X,多个字符n+X
  2. 删除单词dw,删除当前行dd
  3. 替换当前字符r,多个字符n+r,进入替换模式R
  4. 修改当前单词cw,修改多个单词cnw
  5. 字母大小写转换~
移动或复制内容
  1. 复制光标位置当前单词yw,多个单词n+yw
  2. 复制当前行yy,复制多行n+yy
  3. 剪切/删除当前行dd,剪切多行n+dd
  4. 粘贴到当前行下方p,粘贴多次n+p

撤销操作

u

,恢复操作

Ctrl+r

1.3 vim 底行模式命令集

保存退出
  • 底行模式下输入w可以保存文件,输入q可以退出程序。带上!表示强制执行。
显式行号
  • 显示行号set nu,取消行号set nonu
  • 跳转至某行,输入行号n即可。
多文件操作
  • 分屏操作多个文件vs fileName,切换操作文件/光标Ctrl+w+w
查找字符
  1. /Keyword,输入/再输入查找的字符,在按n可以跳转至下一个关键字所在位置。
  2. ?keyword,输入/再输入查找的字符,在按n可以跳转至上一个关键字所在位置。
  3. 可直接使用shift+*,查找当前光标所在的单词。

底行模式命令有很多,目前掌握这几个就行。

Vim 从入门到精通 (github.com)

最全 Vim 键位图 (runoob.com)


2. 编译工具 gcc/g++

gcc/g++ 分别是 C/C++ 的编译器,基本使用方法:

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

接下来将通过使用 gcc 分段编译程序,来熟悉 gcc/g++ 的使用。

2.1 C/C++编译基本步骤

前面已经学过 C/C++ 程序基本的编译过程,也使用过 gcc 进行查看程序的翻译步骤:

  1. 预处理(进行宏替换)
  2. 编译(生成汇编代码)
  3. 汇编(生成机器可识别的二进制文件)
  4. 链接(生成可执行文件或库文件)

预处理
  • 预处理的功能主要包括宏定义,文件包含,条件编译,删除注释等。预处理指令主要指以#开头的语句。
$ gcc -E test.c -o test.i # 完成预处理后停止
  • 选项-E让翻译在预处理结束后停下来,-o可以指定生成的目标文件名,预处理完的文件一般后缀为.i
编译
  • 编译时,gcc 会检查代码的规范性、是否有语法错误,已确定代码所做的工作,检查无误后 gcc 会生成汇编代码。
$ gcc -S test.i -o test.s # 完成编译后停止
  • 编译阶段会生成汇编代码,以供接下来的汇编阶段使用。一般编译结束生成的代码文件的后缀为.s
汇编
  • 汇编阶段将编译所形成的汇编代码生成目标文件,也就是二进制文件。
$ gcc -c test.s -o test.o # 完成汇编后停止

虽然生成的是二进制目标文件,但仍然不可直接运行,准确的来说该文件是可重定向目标文件。相当于Windows下的

.obj

文件。

链接

预处理、编译、汇编三个阶段统称为编译过程,完成了上述编译的过程,就到了翻译环境的最后一个阶段:链接。链接完成之后,就生成了可执行文件。

$ gcc test.o -o test# 完成链接

链接是将所有

.c

源文件所生成的目标文件与语言的链接库文件放到一起进行链接。如图所示:

通常写程序时,就

include

了语言本身所提供的链接库文件,至于链接库文件到底是什么,接下来会讲解。

当然编译 C/C++ 程序,不需要上述这么复杂,直接执行即可:

$ gcc test.c -o test# 1.
$ gcc -o test test.c # 2.

2.2 静态链接和动态链接

函数库的概念

语言本身会提供的库,库可以看成一套头文件和一套库文件。比如通常使用的

printf

,

scanf

等等库函数,都是实现在库文件中的,可以通过引用对应的头文件,来使用这些代码。

使用

lld

命令可以查看可执行程序所依赖的第三方库:

Linux 下的C语言的库文件一般叫作

libc.a

libc.so

,分别是静态库和动态库。Windows 下的静态库和动态库的后缀分别为

.lib

.dll

将用户所写的程序文件和第三方库提供的方法关联起来,这就叫链接。很显然,链接又分为静态链接和动态链接。

由上图可以看出,gcc 默认形成的可执行程序,采用动态链接的方式,因为可执行程序依赖的是动态库。

$ gcc test.c -o test# 默认动态方式
$ gcc test.c -o test_static -static   # 采用静态方式

静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时,下面来详细介绍这两种链接方式。

静态链接

一般开发时,会将代码分离编写到多个

.c

源文件中,而这多个源文件之间不是独立的,可能某个源文件要调用另一个源文件中的函数。

这个调用就发生在目标文件的链接过程中,由链接器在链接时将库的内容拷贝到可执行程序中。然后才能生成可执行程序文件,所以说静态链接发生在形成可执行程序之前

由上图可以看出,静态链接生成的文件比动态链接的体积大得多。

静态链接的优缺点

静态链接的缺点很明显:

  1. 浪费空间,链接时会将库中的内容放入目标文件中,所以文件的体积较大。如果有多个程序文件,那么每个程序中都会加入库文件的内容,包含相同的公共代码,造成浪费。
  2. 更新较为麻烦,每当库函数的代码修改了,此时就需要重新进行重新打包成lib文件,再去编译链接形成可执行程序。

静态链接的优点是,在可执行程序中已经具备了所有执行程序所需要的任何东西,不需要到其他文件中查找内容,在执行的时候运行速度快

动态链接

动态链接出现就是为了解决静态链接中的两个问题:空间浪费和更新困难。 动态链接把程序按照模块拆分成各个相对独立部分,并把链接这个过程推迟到了运行时再进行,由操作系统的装载程序加载库,将它们链接在一起形成一个完整的程序。

假设有两个程序都包含同一个库文件,运行程序1时会将程序1加载到内存中,然后再加载该库文件,再运行程序2时,内存中已有库文件就不会再次加载,直接链接到程序2中即可。

动态链接的优缺点

动态链接的优点是:

  1. 避免空间浪费,即使多个程序依赖于同一个库,但该库不会像静态链接那样在内存中存在多份副本,而是这多个程序执行时共享副本。
  2. 维护比较方便,更新时只需要替换原来的目标文件,程序再次运行时,新的目标文件会自动加载到内存并链接起来。库文件与可执行文件独立,更新库文件不会对程序文件造成影响,提高了可维护性和可扩展性。

动态链接也是有缺点的,因为把链接推迟到了程序运行时,所以每次执行程序都需要进行链接,所以性能会有一定损失,运行速度相对慢一点

深入浅出静态链接和动态链接 (csdn.net)

2.3 gcc 选项

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

3. 调试工具 gdb

gdb 是 Linux 下用于调试代码的工具,这个工具成本高难度也不低且不是很方便直观但仍需掌握。

3.1 背景知识

程序的发布方式有两种模式:Debug 和 Release 模式。Linux 下 gcc/g++ 编译出的可执行程序,默认是 Release 模式。要使用 gdb 调试,必须在代码编译的时候加上调试信息。

$ gcc test.c -o test_debug -g # 加上调试信息
$ gdb test_debug              # 进入gdb调试(gdb) quit                    # 退出gdb

3.2 gdb 选项

调试命令(debug)

名称命令解释开始运行

run

相当于开始调试

F5

,会运行至程序结束逐语句

step

相当于

F11

,有函数会进入函数内部逐过程

next

相当于

F10

,不会进入函数内部,执行整条语句;

像逐过程、逐语句这样的命令一次输入之后,可直接回车仍会再次执行。

显示代码(list)

名称命令解释可指定行号

list + [N]

从第 N 行开始显示10行代码,省略行号就默认从第一行开始打印,可接着上次的位置继续打印可指定函数名

list + Name

从函数起始位置左右开始显示代码。

断点命令(breakpoint)

名称命令解释可指定行号

b + N

在某行打上断点可指定函数名

b + Name

在函数内起始位置打断点查看断点信息

info + b

显示断点信息列表删除断点

d + b [ + N]

删除序号为 N 的断点,省略序号就是删除所有断点启用断点

enable + b [ + N]

启用序号为 N 的断点,省略序号就是启用所有断点禁用断点

disable + b [ + N]

禁用序号为 N 的断点,省略序号就是禁用所有断点

变量命令(variable)

名称命令解释监视变量

display + Name

以列表的形式常显示在屏幕下方,类似于vs中的监视取消监视

undisplay + N

去掉监视列表中的序号为 N 的变量的常显示查看变量

p + Name

打印变量的值,不会常显示修改变量

set + Name

设置指定变量的值

特殊调试命令

名称命令解释结束当前函数

finish

finish 会直接结束当前函数的调用,并停止在函数返回位置,等待接下来的命令继续调试

continue

continue 继续运行至下一个断点,相当于

F5

跳转至指定行

until + N

跳转至当前函数内部的第 N 行
上述三个命令可以快速确定到代码出错的大概范围。

finish

continue

结合在多个函数调用结束的位置检查结果是否正确,定位到出错函数后,可以使用

until

在函数内部查找出错位置。

其他命令

名称命令解释调用堆栈

breaktrace

/

bt

查看程序各级栈帧的调用情况


本文转载自: https://blog.csdn.net/yourfriendyo/article/details/123123600
版权归原作者 AKA你的闺蜜 所有, 如有侵权,请联系我们删除。

“╭(⊙o⊙)ノ★Vim Gcc Gdb★Linux开发三大件熟练指南”的评论:

还没有评论