Linux学习(三)——gdb调试

158 阅读2分钟

Linux学习(三)——gdb调试

基本命令

gdb 可执行文件名
b 函数名或行号
info breakpoints
delete
l 函数名或行号
r 表示运行
q 表示退出
bt 表示列出调用栈
p 变量名 (查看变量名的值)
p/d 变量名 (10进制查看)
p/x 变量名 (16进制查看)
s 表示单步执行,有函数时进函数
n 表示单步执行,有函数时跳过函数
c 表示跳到下一个断点

具体使用

首先写一个测试用的代码:

#include <stdio.h>

int func(int n)
{
    int sum = 0, i;
    for (i = 0; i < n; i++)
    {
        sum += i;
    }
    return sum;
}

void main()
{
    unsigned int i;
    long result;
    int a[200];
    for (i = 1; i < 100; ++i)
    {
        result += i;
        a[i] = i;
    }
    printf("result[1-100] = %d\n", result);
    printf("result[1-200] = %d\n", func(200));
}

在这段代码里面有个小错误,我们先编译一下看看

image.png 接下来,我们使用gdb进入调试:

image.png 接下来我们再使用 l main 命令来查看主函数

image.png 可以看到上述的图片中显示错误,无法执行该命令,这是因为我们之前编译过程没有加上调试的指令,现在我们用q退出,然后重新编译,这时加上 -g

gcc -g test.c -o test1

重新进入调试界面进行调试,可见成功查看了main函数 image.png

在main函数那里设置一个断点,在第18行也设置一个断点 image.png

**查看断点:**使用info breakpoints指令

image.png

**删除断点:**使用 delete 断点Num 的方法

image.png

通过r运行程序,通过n到下一步(这样无法进入到函数里面,如果想要进入到函数里面就使用s命令):

image.png

由上图可见在for循环中,执行了100次,显然我们无法真的执行100次,所以我们可以再设置一个断点, 然后用c指令就可以跳到下一个断点

image.png

我们再次进行调试,这时进入for循环中并查看result的值,很明显可以看到result的值不对劲,那么就是这里出了问题 image.png

在循环中i=50时打个断点的做法: image.png

gdb段错误调试

代码:

#include <stdio.h>

int main(int argc, char *argv[])
{
    char *p = NULL;
    printf("input string:");
    gets(p);
    printf("string is:%s\n", p);
    return 0;
}

这段代码有个很明显的错误,那就是尝试给指向空的空指针赋值。
这里编译一下就可以知道错误: image.png

这时虽然有警告,但是仍然编译成功了,但是我们运行程序的时候就会发现错误: image.png 这种错误是在告诉我们:
1、数组越界;
2、指针没有赋值;
3、通过指针直接访问内存

使用ulimit命令来帮助调试:

指令:

ulimit -c unlimited

如图所示,在使用了该指令后运行文件在提示段错误后会出现一个core文件,这里面就包含了一些文件崩溃的信息 image.png

GDB调试

我们先全部重新编译,重新运行一遍

image.png

接下来再启动gdb

image.png

使用bt查看详情,并把代码拿出来对比,可以看到在#1那一行显示了错误在哪,在#0那一行可以看出来_IO_gets指向的buf=0x0,即为空指针,明显错误。

image.png

多文件调试

这里用到之前makefile中写的几个文件 image.png

然后修改一下makefile文件(要让编译后的文件包含调试信息)

target=myProject
OBJ:=myadd.c mysub.c mymul.c
OBJ+=myProject.c

CC:=gcc
CFLAGS:=-c

$(target):$(OBJ)
	$(CC) -g $^ -o $@

clean:
	rm -f *.o $(target)

然后进入调试,在myAdd那里打个断点(可以看到多文件打断点成功) image.png

接下来在myProject中的main函数和myadd.c的第5行打个断点(通过文件名:行数或函数名) image.png

r一下试试 image.png