C语言gdb调试

news/2025/1/12 18:56:44/

目录

gdb%E4%BB%8B%E7%BB%8D-toc" style="margin-left:0px;">1.gdb介绍

2.设置断点

2.1.测试代码

2.2.设置函数断点

2.3.设置文件行号断点

2.4.设置条件断点

2.5.多线程调试

3.删除断点

3.1.删除指定断点

3.2.删除全部断点

4.查看变量信息

4.1.p命令

4.2.display命令

4.3.watch命令

5.coredump日志

6.总结


gdb%E4%BB%8B%E7%BB%8D" style="background-color:transparent;">1.gdb介绍

        gdb是一个强大的调试工具,广泛用于调试 C、C++ 以及其他编程语言的程序。它帮助程序员在开发过程中识别并修复错误,提高程序的可靠性和性能。

        掌握gdb的基本使用方法非常重要,它能够帮助我们快速定位一些段错误问题或者解决一些程序异常问题。

        如果提示没有gdb命令需要手动安装一下gdb插件:

        在 Ubuntu/Debian 上安装 gdb:sudo apt install gdb

        在 CentOS/RHEL 上安装 gdb:sudo yum install gdb

        日常工作中可以选择gdb启动程序或者gdb -p 程序进程号,来调试程序,章节2,设置断点将会详细讲解。

2.设置断点

2.1.测试代码

        先上一段测试代码,方便讲解设置断点的方法:

main.c文件

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>#define THREAD_NUM 3
#define LOOP_NUM 10void *task(void *arg) {while (1) {int num = *(int *)arg;printf("my num:%d\n", num);sleep(1);}
}void first_print(int num) {printf("first hello: %d\n", num);return;
}void second_print(int num) {printf("second hello: %d\n", num);return;
}void test_copy(char *dest, char *src) {memcpy(dest, src, strlen(src));
}int main()
{char *s = NULL;char *p = "123";//test_copy(s, p);for (int i = 0; i < 10; i++) {first_print(i);second_print(i);}pthread_t threads[THREAD_NUM];int thread_arg[THREAD_NUM] = {0};for (int i = 0; i < THREAD_NUM; i++) {thread_arg[i] = i;pthread_create(&threads[i], NULL, task, &thread_arg[i]);}for (int i = 0; i < THREAD_NUM; i++) {pthread_join(threads[i], NULL);}return 0;
}

 makefile文件:

test:main.cgcc	-O0	-g	-o	test	main.c	-lpthread.PHONY:clean
clean:rm -rf test *.o

        代码功能非常简单,两个打印函数,以及创建3个线程,死循环打印。

2.2.设置函数断点

        函数断点,顾名思义,断点设置在函数上,操作命令: b 函数名

        经过makefile编译后会产生一个test可执行文件,通常来说我们直接gdb可执行文件即可,即gdb test,然后输入r运行程序。

        那么如何设置断点呢,通常可以在执行r命令之前设置断点或者运行过程中设置断点,但是运行过程中设置断点你需要保证程序还没有运行到你将要设置的断点的位置,否则不会命中断点。

        下面我们设置两个函数断点,first_print和second_print,执行b first_print回车然后再执行b second_print即可。

        通过 i b命令查看我们当前设置断点信息,可以看到设置了两个断点,编号分别为1 2 ,然后就可以执行 r 命令运行程序。

        当我们运行程序后,可以看到程序命中了第一个断点,执行c命令, 作用是跳转到下一个断点,执行 n 命令可以运行到一下行。

2.3.设置文件行号断点

        gdb还可以针对文件的某一行设置断点,操作命令:b 文件名:行号

        可以看到我们将断点设置在了main.c文件的第23行,运行程序,程序停止在了23行的位置。

2.4.设置条件断点

        设置条件断点,即再设置断点的基础之上再加上额外的条件,例如某一个变量等于固定的数值,操作命令:b 函数 if (变量 == 常数)

        可以看到我设置了一个断点在函数first_print,且仅当num值为2时命中该断点,运行程序和预期结果一致。

2.5.多线程调试

        在程序中,如果存在多线程的情况,调试起来稍微复杂一些,但是这种场景经常会出现在多核开发环境上,因此需要掌握其调试方法。

        那么如果设置一个断点到一个函数,这个函数会被多个线程调用,那么必定会发生线程切换,因此调试时需要加锁,命令:set scheduler-locking on

        可以看到,将断点设置到了12行,如果不加锁那么这三个线程都会触发这个断点,当第一次触发时我们可以加锁,使得只有当前线程能停在这个断点,若要解锁 ,执行命令:set scheduler-locking off。

        可以看到解锁之后发送了线程切换。

        还有一种方式就是查看当前运行的全部线程,然后进入需要调试的线程。查看全部线程的命令:info threads

        可以看到有三个子线程,然后可以通过thread 线程号 命令,进入具体的线程。

3.删除断点

3.1.删除指定断点

        删除指定断点,操作命令:d 断点编号

        如图,开始设置了两个断点,其编号分别为1 和 2 ,执行命令d 1 删除断点1,然后查看断点情况,只剩下断点2,同理如果要删除断点2,执行命令d 2即可。

3.2.删除全部断点

        删除全部断点,操作命令:d 

4.查看变量信息

        查看变量信息有多种命令,每种命令有不同的作用。

4.1.p命令

        主要用于查看变量的值,操作命令::p 变量名

        如图,执行p num可以查看到num的值。

4.2.display命令

        主要用于一直显示某个变量的值,好处就是不用每次手动执行p命令来查看某个变量的值,操作命令:display 变量名

         如果想取消一直显示,首先执行display,获取id,然后执行命令:undisplay id 即可

 

4.3.watch命令

        watch命令可以追踪某个变量变化前的值和变化后的值,操作命令:watch 变量名

        如果需要需要watch,首先查看所有监视点:info watchpoints,然后执行删除命令,删除指定watch:delete hw watchpoint 3

 

5.coredump日志

        将测试代码第36行,//test_copy(s, p);取消注释,然后重新编译,很明显程序会段错误,此时我们可以执行ulimit -c unlimited,使其可以生产coredump日志文件,然后可以使用gdb调试命令,定位问题,操作命令:gdb 可执行文件名 core文件名

        使用bt命令可以看到具体的调用堆栈信息,然后f id进入具体的函数,通过p命令查看变量的值,很明显dest为空指针。

        

6.总结

        gdb是程序员调试程序不可获取的工具,需要大家多多使用,熟能生巧 。

        注:makefile如果加了-o3编译优化或者其他优化手段,可能在运行时行号会发生跳跃,和预期不一致。


http://www.ppmy.cn/news/1562576.html

相关文章

力扣每日刷题

102. 二叉树的层序遍历 心路历程&#xff1a;一开始想的是使用bfs但是有很多的细节没考虑到&#xff08;不知道如何去处理一层只有一个节点的情况&#xff09;&#xff0c;然后又想到了使用递归回溯的来解决。 解题思路&#xff1a;使用一个总的List来记录所有的List集合&…

基于springboot的医药管理系统源码+论文+开题报告

系统介绍 系统中包含论文和开题报告 今的年代,已经是步入信息社会了,不仅信息更新速度频繁,信息量也大,在信息时代必须有相应的处理信息的方法,如果还采用以前的结绳记事或者笔写纸记,不仅是信息录入效率上赶不上节奏,在信息检索的速度上更是让人无法承受。幸而当今社会…

索引页与B+树的关系

在数据库管理系统中&#xff0c;索引是优化查询性能的核心机制。B树作为一种高效索引结构&#xff0c;与索引页的关联至关重要。下面将详细解释它们之间的关系&#xff1a; 索引页&#xff08;Index Page&#xff09; 索引页是数据库中磁盘块&#xff08;Block&#xff09;的一…

03-51单片机定时器和串口通信

一、51单片机定时器 1.定时器介绍 1.1为什么要使用定时器 在前面的学习中&#xff0c;用到了 Delay 函数延时&#xff0c;这里学习定时器以后&#xff0c;就可以通过定时器来完成&#xff0c;当然定时器的功能远不止这些&#xff1a; 51 单片机的定时器既可以定时&#xff…

【Word_笔记】Word的修订模式内容改为颜色标记

需求如下&#xff1a;请把修改后的部分直接在原文标出来&#xff0c;不要采用修订模式 步骤1&#xff1a;打开需要转换的word后&#xff0c;同时按住alt和F11 进入&#xff08;Microsoft Visual Basic for Appliations&#xff09; 步骤2&#xff1a;插入 ---- 模块 步骤3&…

Python AI教程之十六:监督学习之决策树(7)和其它算法的比较

ML | 逻辑回归与决策树分类 逻辑回归和决策树分类是目前最流行和最基本的两种分类算法。没有哪种算法比另一种更好,而一种算法的优越性通常归功于所处理数据的性质。 我们可以在不同类别上比较这两种算法—— 标准 逻辑回归 决策树分类 可解释性 难以解释 更易于解释 决策…

四种常见的身份认证与授权机制

在现代 web 应用开发中&#xff0c;安全的身份认证和授权机制对于确保数据安全和访问控制至关重要。本文将探讨四种常见的机制&#xff1a;JWT&#xff08;JSON Web Tokens&#xff09;、Session&#xff08;会话&#xff09;、SSO&#xff08;单点登录&#xff09; 和 OAuth 2…

当Elasticsearch索引数据量过多时,可以采取以下措施进行优化和部署

调整索引分片数量&#xff1a;根据数据量和集群规模&#xff0c;重新分配索引的分片数量。较小的索引分片可以提高查询性能&#xff0c;但过多的分片也会增加管理开销。因此&#xff0c;需要根据具体情况进行权衡。调整副本数量&#xff1a;根据数据量和查询负载&#xff0c;适…