C语言gdb调试

目录

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.总结


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 10

void *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.c
	gcc	-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编译优化或者其他优化手段,可能在运行时行号会发生跳跃,和预期不一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/952563.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UML系列之Rational Rose笔记三:活动图(泳道图)

一、新建活动图&#xff08;泳道图&#xff09; 依旧在用例视图里面&#xff0c;新建一个activity diagram&#xff1b;新建好之后&#xff0c;就可以绘制活动图了&#xff1a; 正常每个活动需要一个开始&#xff0c;点击黑点&#xff0c;然后在图中某个位置安放&#xff0c;接…

【CSS】HTML页面定位CSS - position 属性 relative 、absolute、fixed 、sticky

目录 relative 相对定位 absolute 绝对定位 fixed 固定定位 sticky 粘性定位 position&#xff1a;relative 、absolute、fixed 、sticky &#xff08;四选一&#xff09; top&#xff1a;距离上面的像素 bottom&#xff1a;距离底部的像素 left&#xff1a;距离左边的像素…

HTML前端从零开始

第一天 HTML部分 什么是HTML HTML&#xff08;Hypertext Markup Language&#xff09;超文本标记语言。HTML是万维网的基石。 超&#xff1a; 超字第一层意义是指最重要的标签&#xff0c;超链接标签 超越文本的意思 HTML的发展历程 HTML1990年出现&#xff0c;web之父…

Vue2+OpenLayers调用WMTS服务初始化天地图示例(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、WMTS服务详解 四、完整代码 五、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、WMTS服务详解 WMTS&#xff08;Web Map Tile Service&#xff09;是一种标准的网络地图服务协议&#xff0c;用于提供基于…

Linux syslog 运行机制

Busybox的syslogd认识与使用 syslogd 的基本工作原理&#xff1a; syslogd 是一个系统日志守护进程&#xff0c;它接收来自各种进程和系统服务的日志消息&#xff0c;并根据配置将这些消息存储到不同的日志文件中。 syslogd日志记录器由两个守护进程&#xff08;klogd&#x…

离线录制激光雷达数据进行建图

目前有一个2D激光雷达&#xff0c;自己控制小车运行一段时间&#xff0c;离线获取到激光雷达数据后运行如下代码进行离线建图。 roslaunch cartographer_ros demo_revo_lds.launch bag_filename:/home/firefly/AutoCar/data/rplidar_s2/2025-01-08-02-08-33.bag实际效果如下 d…

SDK调用文心一言如何接入,文心一言API接入教程

一、前期准备 注册百度智能云账号&#xff1a; 前往百度智能云官网注册一个账号。这是接入文心一言API的基础。 了解API接口&#xff1a; 在百度智能云开放平台中&#xff0c;找到文心一言API的详情页&#xff0c;了解提供的API接口类型&#xff08;如云端API、移动端API、离线…

CNN张量输入形状和特征图

CNN张量输入形状和特征图 这个是比较容易理解的张量的解释&#xff0c;比较直观 卷积神经网络 在这个神经网络编程系列中&#xff0c;我们正在逐步构建一个卷积神经网络&#xff08;CNN&#xff09;&#xff0c;所以让我们看看CNN的张量输入。 ​ ​ 在最后两篇文章中&…

【Linux】4.Linux常见指令以及权限理解(2)

文章目录 3. Linux指令3.1 ls指令和rm指令补充3.2 man指令&#xff08;重要&#xff09;3.3cp指令&#xff08;重要&#xff09;输出重定向3.3.1ubuntu20.04如何安装tree 3.4 mv指令&#xff08;重要&#xff09;mv指令更改文件名mv指令更改目录名 如何看待指令指令的重命名3.5…

硬件设计-齐纳管

目录 摘要 详情 齐纳管的工作电流、 摘要 齐纳管&#xff08;Zener Diode&#xff09;是一种特殊的二极管&#xff0c;它能够在特定的反向电压下保持电流稳定。正常情况下&#xff0c;二极管只允许正向电流通过&#xff0c;而阻止反向电流流过。而齐纳管在一定的反向电压下可…

C语言进阶——1数据的存储

目录 1. 数据类型介绍1.1 类型的基本归类&#xff1a;1.1.1 整形家族1.1.2 浮点型家族1.1.3 构造类型&#xff1a;1.1.4.指针类型1.1.5 void 表示空类型&#xff08;无类型&#xff09; 2. 整形在内存中的存储2.1 原码、反码、补码2.1.1 示例 20在计算机中的存储 2.2 大小端2.2…

【论文阅读】MAMBA系列学习

Mamba code&#xff1a;state-spaces/mamba: Mamba SSM architecture paper&#xff1a;https://arxiv.org/abs/2312.00752 背景 研究问题&#xff1a;如何在保持线性时间复杂度的同时&#xff0c;提升序列建模的性能&#xff0c;特别是在处理长序列和密集数据&#xff08;如…

数据结构——查找二叉树

二叉搜索树的概念 如图所示&#xff0c;二叉搜索树&#xff08;binary search tree&#xff09;满足以下条件。 对于根节点&#xff0c;左子树中所有节点的值 < 根节点的值 < 右子树中所有节点的值。任意节点的左、右子树也是二叉搜索树&#xff0c;即同样满足条件 1. …

【并发多个请求并失败重发】

文章目录 需求思路代码 需求 可以一次发任意多个请求&#xff0c;如果有失败&#xff0c;则重发失败的请求&#xff0c;知道所有的都成功&#xff0c;或者超出最大重试次数&#xff0c;才返回最终结果。封装成可复用的并发请求工具。 实际的应用场景&#xff1a;数据太大&…

hutool糊涂工具通过注解设置excel宽度

import java.lang.annotation.*;Documented Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) public interface ExcelStyle {int width() default 0; }/*** 聊天记录*/ Data public class DialogContentInfo {/**…

Redis高频知识点

Redis 目录 1 Redis是AP的还是CP的&#xff1f;2 介绍一下Redis的集群方案&#xff1f;3 什么是Redis的数据分片&#xff1f;4 Redis为什么这么快&#xff1f;5 Redis 的事务机制是怎样的&#xff1f;7 Redis的持久化机制是怎样的&#xff1f;8 Redis 的过期策略是怎么样的&a…

shell程序题1.11

作业&#xff1a; shell 脚本写出检测 /tmp/size.log 文件如果存在显示它的内容&#xff0c;不存在则创建一个文件将创建时间写入。 #!/bin/bash#-f 选项来判断 /tmp/size.log 文件是否是一个常规文件if [ -f "/tmp/size.log" ];thencat /tmp/size.logecho "…

Docker: 教程07 - ( 如何对 Docker 进行降级和升级)

如果我们使用 docker 来管理容器&#xff0c;那么保持 docker 引擎的更新将会是十分重要的&#xff0c;这一篇文章我们将会讨论如何对Docker 进行降级和升级。 准备工作 - docker 环境 我们需要拥有一个安装好 docker 的运行环境。 如果你需要了解如何安装 docker 可以通过如…

LabVIEW与CANopen常见问题及解决方法

1. 固件版本不匹配问题 ​ 错误信息&#xff1a; "Firmware image version is incompatible with C Series modules. Solution: Update the firmware by following the instructions in Firmware_Update_Instructions.html, accessible from the National Instruments\NI…

《框架程序设计》期末复习

目录 Maven 简介 工作机制&#xff08;★&#xff09; 依赖配置&#xff08;★&#xff09; Maven命令 MyBatis 入门 单参数查询&#xff08;★&#xff09; 多参数查询&#xff08;★★★&#xff09; 自定义映射关系&#xff08;★★★&#xff09; 基本增删改查操…