【Linux】Linux环境基础开发工具使用(下)

Linux调试器-gdb使用

Ⅰ.背景

Linux下的程序调试与在Windows下的调试的思路是一样的,但是方法不一样。Windows下调试程序是在图形化界面进行的,而Linux下的调试是命令行调试。

● 程序的发布方式有两种,debug模式release模式
● Linux gcc/g++出来的二进制程序,默认是release模式,该模式下无法进行调试。如果硬进行gdb调试的话,可能会出现下图所示状况

 (gdb) l
No symbol table is loaded.  Use the "file" command.

● 要使用gdb调试,必须在源代码生成二进制程序的时候, 加上 -g 选项。例如
gcc -g test.c -o test_g

注意:
第一次使用gdb之前,需要安装gdb,指令是

sudo yum install -y gdb

debug模式发布的二进制程序比release模式发布的二进制程序所占空间小
debug模式**和**release模式
其中test是release模式,test_g是debug模式

面试题:Linux下的默认行为有哪些?
gcc:默认行为
1.默认是动态链接的
2.默认是release模式

vim:默认行为
默认打开就是命令模式

Ⅱ. gdb基本操作

💡tips:gdb会默认记录最近依次使用的指令,按回车可以再次执行该条指令

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

注意:

调试程序完毕,或者调试中间过程,调试痕迹很重要,当调试一个大的项目,可能有几十个断点,某个断点调试完了,不要直接把它删除,而是暂时禁用它,等程序没有任何问题了,再把所有断点删除。

Linux项目自动化构建工具-make/Makefile

Ⅰ.背景

  • ● 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力 ●
    一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
    ● makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
    ● make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual
    C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。
    make是一条命令,makefile是一个文件,makefile内部要写的是依赖关系和依赖方法,两个搭配使用,完成项目自动化构建。

Ⅱ.基本使用

假如我现在编写了一个 test.c 文件,需要编译文件生成可执行程序:

方式一:直接使用 gcc 命令:

gcc test.c -o test

方式二:可以用 make 命令:想要使用 make 命令,需要创建一个 makefile 文件,如何创建 makefile 文件呢?先看看make命令的使用实例,见见猪跑!

Makefile文件:
  1 test:test.c
  2     gcc test.c -o test
  3 
  4 .PHONY:clean
  5 clean:
  6     rm -f test    

执行:
[hutao@hecs-414761 ~]$ make
gcc test.c -o test

这样也可以形成test这个可执行二进制程序

Ⅲ.依赖关系和依赖方法

依赖关系

● 上面的文件 test ,它依赖 test.c

依赖方法
gcc test.c -o test ,就是与之对应的依赖关系

原理
make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。
  3. 如果test文件不存在,或是test所依赖的后面的test.c文件的文件修改时间要比test这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成test这个文件。
  4. 如果test所依赖的test.c文件不存在,那么make会在当前文件中找目标为test.c文件的依赖性,如果找到则再根据那一个规则生成test.c文件。(这有点像一个堆栈的过程)
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成 test.c 文件,然后再用 test.c 文件声明make的终极任务,也就是执行文件test了。
  6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
  8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
  9. 如果make后不加目标文件名,则会按照makefile中从上到下的第一个目标文件。

多文件编译
在一般的工程项目中,有着许多的源文件,面对着众多的源文件,可能会面临一些问题:

  1. 在执行依赖方法时,若不小心将源文件与生成的文件的位置写错或写反时,可能会将源代码直接覆盖掉了,从而找不到源代码了。
  2. 一个中大型的项目有着非常多的文件需要进行编译,每次需要重新生成可执行程序都要将各个文件的关系理清,然后分别进行编译,gcc/g++的指令也随之变长,这是一件非常麻烦的事,而且容易出错。

针对多文件的项目,就需要使用 make/makefile 了,这将降低编译文件的出错率,提高工作效率。

Ⅳ.makefile文件的创建与使用

1.在当前目录下创建一个名字叫“Makefile”或“makefile”的文件

make 是依赖于 makefile 的,要运行 make ,当前目录下就必须要有名为 makefile的文件。makefile 是阐述依赖关系和依赖方法的。makefile 文件命名只能是 makefile/Makefile两种命令方法。

在这里插入图片描述
2.编写 makefile/Makefile 文件并保存。依赖关系与依赖方法相互搭配,依赖方法必须以 Tab 键开头。
在这里插入图片描述
3.编写好 makefile 后,若需要生成可执行程序,直接在命令行中输入 “make” 即可
在这里插入图片描述

Ⅴ.项目清理

  • 工程是需要被清理的
  • clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
  • 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的,不受其他因素限制
    在这里插入图片描述

Ⅵ.关键字.PHONY

.PHONY:用该关键字修饰的是一个伪目标,该目标总是被执行的,不受其他条件的越苏。上图中,生成可执行程序的依赖关系和依赖方法没有被 .PHONY 修饰,因此 make 命令执行生成了可执行程序之后,若源文件没有被修改过的话,再次执行 make 命令是不会执行成功的。
在这里插入图片描述

而需要被清理的可执行程序用 .PHONY 修饰了,所以每次执行 make clean 时,都是执行写入的依赖方法。
在这里插入图片描述
那么问题来了,makefile 是如何识别 exe/bin 是新的还是旧的,源文件有没有被更改过呢?
使用 stat 命令可以查看程序或文件的三个时间:

1. Access 表示最近一次访问该文件的时间
2. Modify 表示文件最近一次被修改的时间
3. Change 表示文件属性更改的最近时间

在这里插入图片描述
注意:

  • 当你修改文件内容的时候,可能会导致该文件的大小也改变了,此时Modify时间和Change时间会同时改变
  • 当你访问一次某个文件时,它的Access时间可能不会改变。因为在我们进行文件操作的时候,访问文件的次数是要多余该文件的次数的,如果每次访问都要修改Access时间的话,Access时间就被修改的太频繁了,而修改Access时间会访问磁盘,如果多次修改就会降低效率。因此,只有当你在短时间内连续多次访问该文件,它的Access时间才会改变。

可执行程序是由源文件生成的,所以源文件的 Modify 时间要早于可执行程序的 Modify 时间,因此,gcc/g++ 只需要对比源文件与可执行程序的最近修改时间(Modify),便可知道程序是否需要重新生成。若可执行程序的 Modify 时间早于源文件的 Modify 时间,说明源文件被修改过,则需要编译程序生成新的可执行程序,否则不需要重新进行编译。

注意:若可执行程序是最新的,不能再次生成新的可执行程序。若需要再次生成新的可执行程序,可以使用 touch 文件名更新文件/程序的三个时间为当前执行命令的最新时间。
touch test.c // 将该文件的三个时间更新为当前的最新时间

Ⅶ.makefile的推导规则

以程序生成的四个阶段:预处理、编译、汇编、链接为例:

当前文件夹中只有test.c和makefile这两个文件
在这里插入图片描述
makefile文件内容:
在这里插入图片描述
当执行make指令时,会默认致生成第一个目标文件test,而文件test依赖文件test.o,文件test.o依赖文件test.s,文件test.s依赖文件test.i,文件test.i依赖文件test.c,这样就会一直往下找,然后依次生成每个所依赖的文件
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值