Ubuntu系统使用gdb调试C程序

本文目的是通过在Ubuntu系统18.04上使用gdb调试器调试C语言程序,在调试的过程中深入了解gdb调试器的用法并且熟练掌握Linux系统下gdb调试器的使用。

(一)初识gdb

1.gdb简介

  • GDB : GNU Debugger,是GNU工程为GNU操作系统开发的调试器,但它的使用不局限于GNU操作系统, GDB可以运行在UNIX、Linux甚至Microsoft Windows。GDB可以调试C、C++、Objective-C、Pascal、Ada等语言编写的程序;被调试的程序可以跟GDB运行于同一台电脑,也可运行于不同电脑。
  • GDB的功能:
    (1)设置断点使程序停住
    (2)监视或修改程序中变量的值
    (3)跟踪代码执行过程

2.启动gdb

  • 编译时添加调试信息
    程序要能被调试,必须包含调试信息。编译程序时,通过gcc的-g选项为程序添加调试信息。命令如下:gcc –g –o hello hello.c或者gcc -g hello.c -o hello(这里以hello.c为例)
  • gdb调试程序
    使用命令gdb hello即可进行该程序的调试

3.gdb相关命令

命令作用
file装入想要调试的可执行文件。
kill终止正在调试的程序。
list列出产生执行文件的源代码的一部分。
next执行一行源代码但不进入函数内部。
step执行一行源代码而且进入函数内部。
run执行当前被调试的程序。
continue继续运行程序。
quit终止gdb。
watch使你能监视一个变量的值而不管它何时被改变。
backtrace栈跟踪,查出代码被谁调用。
print查看变量的值。
make使你能不退出gdb就可以重新产生可执行文件。
shell使你能不离开gdb就执行UNIX shell命令。
whatis显示变量或函数类型。
break在代码里设断点,这将使程序执行到这里时被挂起。
info break显示当前断点清单,包括到达断点处的次数等。
info files显示被调试文件的详细信息。
info func显示所有的函数名称。
info local显示当函数中的局部变量信息。
info prog显示被调试程序的执行状态。
delete [n]删除第n个断点。
disable[n]关闭第n个断点。
enable[n]开启第n个断点。
ptype显示结构定义。
set variable设置变量的值。
call name(args)调用并执行名为name,参数为args的函数。
Finish终止当前函数并输出返回值。
return value停止当前函数并返回value给调用者。

(二)执行程序时出错

1.源程序

  • RevertNum.c
#include<stdio.h>

void ShowRevertNum(int Num)
{
	while(Num>10)
	{
		printf("%d",Num%10);
		Num/=10;
	}
	printf("%d\n",Num);
}

int main()
{
	int n;
	printf("Please input a number:");
	scanf("%d",&n);
	printf("After Revert:");
	ShowRevertNum(n);
	return 0;
}
  • Seg_Demo.c
#include<stdio.h>

int main()
{
	int *p=0;
	*p=1;
	return 0;
}

2.遇到的问题

  • 编译生成的RevertNum倒序输出程序在输入100时出错
    RevertNum
  • 编译生成的Seg_Demo程序执行时显示段错误
    Seg_Demo

(二)gdb调试解决问题

1.gdb调试RevertNum程序

  • 首先,生成可调试的程序(命令:gcc -g RevertNum.c -o RevertNum
    gcc-g

  • 其次,进入调试(命令:gdb RevertNum
    gdb

  • 显示源程序代码,便于设置断点调试程序(命令:list或者l
    gdb-l

  • 设置并查看断点

    • 设置断点命令:break n或者b n,n为需要设置断点所在行数
      gdb-b
    • 查看已设置断点命令:info b
      gdb-info-b
  • 执行程序

    • 由于设置了断点,因此程序运行到断点时会停下来方便调试。
      run-b
    • 分析程序错误的原因:
      这里我设置了三个断点,分别在第5、8、10行处。程序运行到第一个断点处Num的值为100;再次运行直接跳到第三个断点处时Num的值仍为100,;再次运行程序结束,输出为After Revert:100。为什么程序没有在第二个断点处停下来?原因是程序没有执行while循环里的语句,当传入的参数等于100时不满足该语句,因此不会执行while循环里的语句。
    • 修改方法:
      将该while(Num>10)改为while(Num>=10)即可。

2.gdb调试Seg_Demo内存出错的程序

  • 首先和上面一样,生成可调试的程序Seg_Demo
    gcc-Seg
  • Linux中,程序崩溃时,一般会产生core文件,记录进程退出前的状态,调试段错误问题,借助于该文件,可快速定位问题。
    • 可按如下步骤生成和使用core文件
      (1)让系统产生core文件
      ulimit –c num	#设定core文件容量(num为数字,为0是不产生core文件) 
      
    (2)运行程序,让程序崩溃,从而生成core文件
    (3)gdb配合core文件,定位问题。命令:gdb 程序名 core文件名
    • 产生core文件
      gdb-core
  • 其次,开始调试
    • 使用命令l显示源代码
    • 使用命令b n(n为需要设置的断点行数)设置断点
    • 使用命令info b查看断点
      gdb-l-core
  • gdb执行命令r时显示如下错误
    r-err
  • 继续调试该程序
    调试时显示整型指针p的地址为0x0,而该地址一般不允许访问,因此造成了内存错误。
    gdb-b-err
  • 参考解决方法
    给整型指针p分配地址,这样一般就不会出现内存错误的问题了。当然,这也有其他的方法,大家可以去自行探索。
    #include<stdio.h>
    #include<stdlib.h>
    
    int main()
    {
    	int *p;
        p=malloc(sizeof(int));
        *p=1;
        free(p);
        return 0;
    }
    

(三)总结

通过在Ubuntu系统使用gdb调试器对C程序进行调试,我发现Linux操作系统与windows系统调试程序完全是不一样的体验。gdb调试器让我对于底层C语言的调试有了更加清楚的认识,而windows系统上的IDE虽然方便了调试,但却看不见C语言的底层调试时如何完成的,这也是gdb调试程序的好处之一。希望自己在以后gdb的使用中可以了解得更加深入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值