栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【C语言基础】gdb调试工具的使用

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C语言基础】gdb调试工具的使用

gdb调试教程 快速入门

要想快速入门gdb调试,可以直接翻阅基本案例:采内存

介绍

GDB是一个由GNU开源组织发布的、UNIX/LINUX操作系统下的、基于命令行的、功能强大的程序调试工具。 对于一名Linux下工作的c/c++程序员,gdb是必不可少的工具

常用指令

shell 指令

指令用法介绍
gdbgdb +${exe}对生成的可执行文件进行调试
gdb -qgdb -q +${exe}对生成的可执行文件进行调试
表示不打印gdb版本信息,界面较为干净;

gdb指令

指令用法介绍
断点设置
breakbreak + L i n e < b r > b r e a k + {Line}
break + Line
break+{func}
可以对行号和函数进行设置断点
程序运行
runrun / r首次运行程序,运行到第一个断点
continuecontinue / c继续运行程序,运行到下一个断点
nextnext / n单步跳过,(执行一步程序,遇到函数,直接完成函数操作,不会进入函数)
stepstep / s单步进入,(执行一步程序,遇到函数会进入)
untiluntil / u + ${Line}跳出循环体,并跳到循环体外部的某一行
变量查看
printprint +变量打印变量的值
whatiswhatis +变量打印变量的类型
quitquit / q退出
可视化
layout src调试的时候同时显示源代码窗口,但是必须run之后才会显示
基本案例:采内存 0. 源码

本案例以下文段错误(采内存)源码进行介绍如何进行gdb调试。

通常在复杂程序调用中,指针的操作容易导致编程人员对内存空间的使用造成困扰和混乱,因此指针操作是导致内存异常问题最为常见的因素也是最难定位的因素。

源代码如下:

在本案例中,main函数里的my_user指针在addUser函数里进行资源申请。虽然成功申请到了堆中的空间。但是因为my_user是作为参数传入,因此在函数返回时,my_user又重新指向了NULL,而非堆上的空间地址导致运行发生段错误。

#include 
#include 

typedef struct User {
	int id;
	int age;
} User;

void addUser(User *user, int id, int age)
{
	user = (User *)malloc(sizeof(User));
	user->id = id;
	user->age = age;
	printf("id = %d, age = %dn", user->id, user->age);
}

int main()
{
	printf("gdb demon");
	User *my_user = NULL;

	addUser(my_user, 10, 20);
	printf("id = %d, age = %dn", my_user->id, my_user->age);

	return 0;
}
1. 编译

要想使用gdb调试功能,需要在gcc编译器添加-g参数,或者在cmake里编译成debug模式。

>> gcc -g -o main main.c
2. 打开gdb调试
>> gdb main 
>> gdb -q main # 表示不打印gdb版本信息,界面较为干净;
3. gdb 设置断点

breakinfo breakpoints

# 使用 break 或者 b 进行设置断点。
# 可以对函数进行打点,或者对代码行进行打点。
# 我们可以使用info breakpoints查看当前所有的断点信息
(gdb) b addUser 
Breakpoint 1 at 0x752: file gdb_test.c, line 11.
(gdb) b 13
Breakpoint 2 at 0x769: file gdb_test.c, line 13.
(gdb) b 20
Breakpoint 3 at 0x7aa: file gdb_test.c, line 20.
(gdb) info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000000752 in addUser at gdb_test.c:11
2       breakpoint     keep y   0x0000000000000769 in addUser at gdb_test.c:13
3       breakpoint     keep y   0x00000000000007aa in main at gdb_test.c:20 
4. 运行

runcontinuenextstep

# 当我们设置完断点进行调试的时候,首先要执行run函数开启程序进程,run会执行到第一个断点位置
# 然后我们可以执行next 或者 continue 或者 step进行推进程序
# continue: 运行到下一个断点
# next: 单步跳过,(执行一步程序,遇到函数,直接完成函数操作,不会进入函数)
# step: 单步进入,(执行一步程序,遇到函数会进入)
(gdb) run
Starting program: /home/rodney/ProjectCode/Cproject/C_coding/gcc&g++&gdb_block/bug1/main 
gdb demo

Breakpoint 3, main () at gdb_test.c:20
20		User *my_user = NULL;
(gdb) n
22		addUser(my_user, 10, 20);
(gdb) c
Continuing.

Breakpoint 1, addUser (user=0x0, id=10, age=20) at gdb_test.c:11
11		user = (User *)malloc(sizeof(User));

(gdb) c
Continuing.

Breakpoint 2, addUser (user=0x555555756420, id=10, age=20) at gdb_test.c:13
13		user->age = age;

(gdb) n
14		printf("id = %d, age = %dn", user->id, user->age);
(gdb) n
id = 10, age = 20
15	}
(gdb) n
main () at gdb_test.c:23
23		printf("id = %d, age = %dn", my_user->id, my_user->age);
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x00005555555547cc in main () at gdb_test.c:23
23		printf("id = %d, age = %dn", my_user->id, my_user->age);

从上文可以看出是23行打印发生了报错,那么如何确定23行的打印发生了什么具体错误,可以使用print和whatis进行打印显示。

5. 打印和显示变量信息

print 打印变量的值whatis 打印变量的类型

# 从打印的信息可以看出,这里my_user是个空指针,因此访问出现上文的段错误。
(gdb) whatis my_user
type = User *
(gdb) whatis my_user->id
type = int
(gdb) print my_user
$1 = (User *) 0x0
(gdb) print my_user->id
Cannot access memory at address 0x0
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/737672.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号