Linux gdb调试C语言程序

gdb常用命令

gdb在命令的首字母唯一时是可以缩写的。

  • b/break 函数名:给函数设置断点。

  • c/continue:继续执行。

  • b/break 文件名.c:行号:在指定文件的指定行设置断点。

  • next:单步执行程序,如果是函数则将函数整体执行,不会进入

  • 回车键:执行上次的命令。

  • file 可执行文件名:调试指定的文件。

  • s/step:单步执行程序,如果是函数则会进入

  • l/list:显示当前行下面的10行代码。

  • p/print 变量名:查看变量的值。也可以查看函数的值(地址)。

  • i/info b/break:查询断点信息。

  • d/delete:删除所有的断点。

  • d/delete 断点序号:删除第几个断点。

  • attach pid:调试运行中的进程id为pid的程序。

demo1

#include 

int add(int num1, int num2){
	return num1 + num2;
}

int main(){
	int a = 5;
	int b = 8;
	int ret = add(a,b);
	printf("%d + %d = %d\n", a, b, ret);
	return 0;
}

生成可执行文件

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

调试

选中编译文件

调试必须在编译时加入 -g,然后再输入file 可执行文件名,编译时如果没有指定文件名,默认是a.out
Linux gdb调试C语言程序_第1张图片

查看代码

每次l命令只能看10行。
Linux gdb调试C语言程序_第2张图片

运行代码

Linux gdb调试C语言程序_第3张图片

设置断点(函数)

Linux gdb调试C语言程序_第4张图片

  • 先在add函数处添加了断点,然后直接运行程序。

  • 然后就停在了第4行(实际上是从第10行调用的),也就是add中return的位置。
    Linux gdb调试C语言程序_第5张图片

  • 执行n指令,继续走一步,来到第五行。

  • 再次执行n指令,也就是ret赋值完毕,来到第11行。

  • 按下回车,执行上一次的指令,也就是n,执行printf语句打印出信息,显示了下一行的语句:return 0;

打印变量信息

Linux gdb调试C语言程序_第6张图片

断点情况

  • 查看断点
    Linux gdb调试C语言程序_第7张图片
  • 删除指定断点
    在这里插入图片描述
    只有一个断点,删除了一号断点后,就没有断点了。

demo2

#include 
#include 

void printHello(int times){
	printf("Hello -- %d\n", times);
}

int main(){
	for(int i=0;i<10000;i++){
		printHello(i);
		sleep(3);  // 睡眠3秒
	}
	return 0;
}


生成可执行文件

for循环如果报错,要加一个-std=c99
-o 可以指定可执行程序的名称,这里我将demo2.c的可执行文件名称指定为demo2
Linux gdb调试C语言程序_第8张图片
测试一下:
Linux gdb调试C语言程序_第9张图片

如果打印操作不是通过printHello函数,并且printf中没有\n,那么是没有打印结果的。
需要加上\n,或者是fflush(stdout);刷新一下缓冲区。
这是因为printf的输出结果被放在缓冲区,如果没有换行符或者刷新缓冲区,不会有输出。

调试

这次我们要调试运行中的程序,所以要获取该程序的进程id
ps -ef | grep 进程名
先运行程序,然后从另一个终端中搜索该程序的进程号:
在这里插入图片描述

这里的10237就是PID(process identity)

调试运行中的程序

Linux gdb调试C语言程序_第10张图片

  • attach 10237:调试PID为10237的程序。
  • b demo2.c:10demo2.c的第10行打一个断点,同时左边终端到Hello --58就停住了,没有再输出信息。
  • 执行一步,也就是执行sleep(3),提示我们下一次要执行的是:
9		for(int i=0;i<10000;i++)\{

也就是第9行的for循环体。

  • 查看i的值
    Linux gdb调试C语言程序_第11张图片
  • 再执行一步
    在这里插入图片描述
  • 这里用s再执行下一步,s是会进入函数的,s就是step的缩写
    在这里插入图片描述
    Linux gdb调试C语言程序_第12张图片

果然进入了第5行的函数体中。

  • 我们使用c命令,也就是continue:继续执行代码,因为我们设置过断点,所以会来到调用函数的地方。
    Linux gdb调试C语言程序_第13张图片
  • 这里我们用n,来看看是否会进入函数。
    Linux gdb调试C语言程序_第14张图片
    发现是没有的,程序直接执行完了当前行,并且下一行要执行sleep(3)
    也打印出了结果。当然,Hello --59是上一次打印的。
    Linux gdb调试C语言程序_第15张图片
  • 我们还可以通过kill命令结束程序。
    kill命令不是gdb中的,所以我们要先通过qquit退出gdb的shell,调试会话还没结束,它会问你一下要不要退出,我们输入y
    Linux gdb调试C语言程序_第16张图片
    我们一结束调试,旁边的终端就又开始输出信息了。等着,马上kill掉它。
    Linux gdb调试C语言程序_第17张图片
    进程被kill掉,程序就结束啦。
    在这里插入图片描述

你可能感兴趣的:(C/C++,linux,c语言,运维)