gdb调试教程

2023-11-07

gdb调试是c/c++代码调试最重要的工具了,我们今天来系统熟悉一下。

——————————————————————————————————————

太长不看版

(注意,如果针对cmake项目,需要把编译模式从release改成debug,否则无法定位到准确的行数)

  • 进入gdb debugger界面==>gdb filename  示例:gdb helloworld.cpp
  • 查看segmentation fault 位置:
    run
    backtrace
  • 加断点: break filename:line   
    • 示例:break helloworld.cpp:10
  • 加条件断点: break filename:line if (condition) 
    • 示例:break helloworld.cpp:10 if (i ==10)
  •  查看局部变量: print(variable) 
    • 示例:print i 
  • 运行 run
  • 继续运行 continue
  • 运行下一个指令 next
  • 进入一个函数体 step into 
  • 观察一个变量 watch 

——————————————————————————————————————

手把手教学版

先上一段充满bug的代码:

#include <stdio.h>
#include <stdlib.h>
 // this function is 100% correctly implemented

void print_heart();
void times_two(int *num) {
  // calculate 2*num
  for (int i = 0; i < *num; i++) {
    *num++;
  }
}

 

 
int main(int argc, char *argv[]) {
  // parse arguments
  if (argc != 2) {
    printf("usage: %s <number>\n", argv[0]);
    return 1;
  }
   print_heart();
 
  // allocate memory
  int *number = malloc(sizeof(int));
  if (number = NULL)
    return 1;
  *number = atoi(argv[0]);

  // calcualte and print result
  times_two(number);
  printf("Result: %d\n", *number);

  // free memory
  free(number);
  return 0;
}

void print_heart() {
 
	int i, j;
	for (i = 0; i < 3;i++)
	{
		for (j = 0; j < 5-2*i;j++)
		{
			printf(" ");
		}
		for (j = 0; j < 5+4*i;j++)
		{
			printf("❤");
		}
		for (j = 0; j < 9-4*i;j++)
		{
			printf(" ");
		}
		for (j = 0; j < 5+4*i;j++)
		{
			printf("❤");
		}
		printf("\n");
    }
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 29;j++)
			printf("❤");
		printf("\n");
 
	}
	for (i = 0; i < 6+ 1; i++)
	{
		for (j = 0; j < 2*i+1; j++)
			printf(" ");
		for (j = 0; j < 27-4*i; j++)
			printf("❤");
		printf("\n");
	}
	for (i = 0; i <1; i++)
	{
		for (j = 0; j < 14; j++)
			printf(" ");
		for (j = 0; j < 1; j++)
			printf("❤");
		printf("\n");
	}
 

 
}

这个代码的作用是打印一个骚气的爱心,然后,将输入的数字×2.(显然,刚开始,代码不能实现这样的功能)

用gcc编译改代码:

gcc -g -std=c99 -o bug bug.c

#run
./bug 3

你会发现有core dump,所以,接下来开始debug

启动gdb

gdb --args ./bug 10

这时,你会发现,Terminal左边出现了(gdb)

然后输入“run”

从终端可以看到,在28行出现错误,然后对应代码;

28行涉及到的变量包括number,和右边的参数。我们可以用gdb显示变量的数值,所以来看看number吧。

通过检查,发现number指向了一个nullptr,这显然不是我们期望的。再来看看argv[0], 发现它是一个

我们希望的是把输入char改成int类型,但是,发现它不是这样的。所以,对代码修改。

重新编译,使用gdb

从结果上看,还是一样的错误。

但是,这时候如果打印会发现;

所以,右边的数值是我们期待的,去除了一个bug。。。只是左边还是一个nullptr。

因为程序一旦碰到bug结束,就要重新运行,所以调试的时候,我们希望一步一步,就需要加breakpoint。在之前的代码里,在28行出现了问题,所以我们需要在这之前添加断点,我们关注的变量是number,因此,我选择了在25行添加断点。

注意,断点打在25行意味着,25行还没有被执行

我们执行next,来跑下一行代码,对应的就是25行,这时候,可以发现,和我们的预期一样,number是一个有效地址。继续next,然后在28行,地址重新变为了0。 

所以问题其实就找到了。在26行的判断语句中,我们把number重新赋值为null。所以,赶紧修改, 重新编译

继续在28行打断点,然后next break bug.c 28

发现,*number = 10, 现在正常了

然后,自信的continue

但是,结果是不对的。。。重新输入run,next。

通过step,我们可以进入函数,

输入list,我们可以在终端查看代码

print i 会发现 i对应的是一个奇怪的数字,因为还没有初始化。

接着,next

这时候,print 就得到了 0

通过操作,我们发现,在for循环中,增加的是地址,而我们希望的是,增加地址对应的数的大小。

所以,修改代码。

接下来重新编译,然后这次我们在函数循环的开始处加断点,这时候,我们观察num对应的地址,没有改变,说明改变是生效可行的。

我们假设程序是正确的,直接continue,这时候,其实还是naive了。结果是错的。

重新run,继续debug,

我们在循环开始的地方加上断点,因为我们想知道进入循环之前的状态

我们加上一个条件断点,因为我们关心当在循环中满足条件时,为什么没有正常退出。我们关注×num最后一次做加法的情况,也就是×num=19==》后来测试发现,在下一行观察number和i似乎更有效。。。。

这时候,其实结果很明显了

懂得都懂,不懂的也不方便多说,这行水太深。我们对程序进行修改。

还有一个重要功能:

backtrace: 可以查看代码嵌套的过程。并且,非常适合找到segmentation对应的行数。

-------------------------------------------------------------------------------------------------------

更新: 当程序启动后,依旧另外启动终端,将GDB介入,进行debug,方法如下:

首先利用关键词找到需要debug的程序的Process ID。

ps -ef | grep [keyword]

然后,执行

sudo gdb -p 29925
#将29925替换为你要找的pid

这样,你就可以介入进行debug了

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gdb调试教程 的相关文章

  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 为什么 C# Array.BinarySearch 这么快?

    我已经实施了一个很简单用于在整数数组中查找整数的 C 中的 binarySearch 实现 二分查找 static int binarySearch int arr int i int low 0 high arr Length 1 mid
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • Asp.NET WebApi 中类似文件名称的路由

    是否可以在 ASP NET Web API 路由配置中添加一条路由 以允许处理看起来有点像文件名的 URL 我尝试添加以下条目WebApiConfig Register 但这不起作用 使用 URIapi foo 0de7ebfa 3a55
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 使用 WebClient 时出现 System.Net.WebException:无法创建 SSL/TLS 安全通道

    当我执行以下代码时 System Net ServicePointManager ServerCertificateValidationCallback sender certificate chain errors gt return t
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • SolrNet连接说明

    为什么 SolrNet 连接的容器保持静态 这是一个非常大的错误 因为当我们在应用程序中向应用程序发送异步请求时 SolrNet 会表现异常 在 SolrNet 中如何避免这个问题 class P static void M string
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • cmake 将标头包含到每个源文件中

    其实我有一个简单的问题 但找不到答案 也许你可以给我指一个副本 所以 问题是 是否可以告诉 cmake 指示编译器在每个源文件的开头自动包含一些头文件 这样就不需要放置 include foo h 了 谢谢 CMake 没有针对此特定用例的
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • C# 模拟VolumeMute按下

    我得到以下代码来模拟音量静音按键 DllImport coredll dll SetLastError true static extern void keybd event byte bVk byte bScan int dwFlags

随机推荐

  • Java Swing实现美化版绘图工具

    美化版画图工具功能模块分析 gitee https gitee com Guo HongYan javaShape git github https github com 229976762 Java git aliyun https ww
  • R语言基础4 (R运算符)

    R运算符 算数运算符 算数算符 算符含义 乘幂 乘 除 加 减 模运算 取余数 整数除法 例子 gt a lt 10 gt b lt 2 gt c lt 3 gt a b 1 100 gt a b 1 20 gt a c 1 3 33333
  • pc端和移动端抓包工具

    客户端与服务器端 CydiaSubstrate框架 Frida Native层HOOK Frida hook Java层 需要相关资料的朋友 可以 加入此处即可打包获取 一 抓包工具概述 http https fiddler burpsui
  • ssl证书过期;申请以及Nginx配置。

    1 登录阿里云 工作台找SSL证书或者安全下找CA证书 2 点击创建证书 或购买证书 创建好以后点击证书申请 3 设置配置以及域名信息 仅填写圈住内容 其他默认即可 4 随后等待一会 查看状态 是否为 已签发 5 为已签发时 点击下载选择下
  • Linux — 【进程信号】

    目录 一 信号的概念 那么生活中的信号有哪些呢 如何把上面的概念迁徙到进程中呢 signal函数 二 信号的产生 1 通过终端按键产生信号 2 调用系统函数向进程发信号 kill函数 raise函数 abort函数 3 硬件异常产生的信号
  • Django Vue corsheaders跨域问题

    跨域问题 记录一下在我自己的django vue项目里面出现的跨域问题 我的项目之前一直是在本地跑的 因为需要上线测试 所以我就运行在同一个vlan里面 ip段 192 168 1 0 24 突然发现存在跨域问题 我django的接口访问被
  • CC2530定时器使用笔记

    最近在用2530的定时器做捕捉和生成pwm 其中一块2530负责捕捉 另一块2530负责生成pwm 整理下笔记 方便以后查阅 一 普通定时 使用定时器来定时将tick自加 获得更精确的时间 代码如下 在其他地方将系统的时钟配置了32M 此处
  • BES提示音修改实验

    加v hezkz17 进数字音频系统答疑群 1 普通提示音切换需要注意的 比如切换不同的音频信号源注意先要app audio list clear 然后再切换音频app audio manager sendrequest APP BT ST
  • Vuex状态管理器

    目录 1 什么是vuex 2 vuex的使用场景 3 vuex的工作方式 4 vuex的核心API 1 state 2 mutations 3 actions 通过actions去触发mutations中的方法 实现对state的异步修改
  • 微信小程序的使用教程

    一 首先我们要去安装一个微信开发者工具 微信开发者工具下载 二 注册一个微信小程序 生成ID 注册链接 注册好之我们打开开发管理 开发设置 复制App的ID 三 打开微信开发者工具 按图示填写完整之后 我们点击确定 这样你就创建好了一个小程
  • Windows安装GPU环境CUDA、深度学习框架Tensorflow和Pytorch

    Windows安装GPU环境CUDA 深度学习框架Tensorflow和Pytorch 1 未安装CUDA使用tensorflow报错 import tensorflow as tf 2022 03 06 15 14 38 869955 W
  • JavaScript数据类型

    变量 1 概述 变量 variables 是计算机内存中存储数据的标识符 根据变量名称可以获取到内存中存储的数据 甚至数据可以修改 变量相当于一个容器 内部可以存储任意类型的数据 使用变量时 用的是内部存储的数据 本质 变量是程序在内存中申
  • 服务器发送消息到客户端互斥,分布式相关/Zookeeper.md · 。W/Java-info - Gitee.com

    Zookeeper 概述 ZooKeeper是一种分布式协调服务 用于管理大型主机 在分布式环境中协调和管理服务是一个复杂的过程 ZooKeeper通过其简单的架构和API解决了这个问题 ZooKeeper允许开发人员专注于核心应用程序逻辑
  • Linux服务器上通过miniconda安装R(2022)

    安装miniconda 下载最新版miniconda wget https repo continuum io miniconda Miniconda3 latest Linux x86 64 sh 安装 bash Miniconda3 l
  • IoT reigns supreme at upcoming Embedded Linux Conference

    本文转载至 http linuxgizmos com linux foundation details embedded linux conference agenda 转载说明 今年的嵌入式 Linux 大会内容非常丰富 包括 Linus
  • ImportError: PILKit was unable to import the Python Imaging Library.

    migrate数据到数据库时遇到的错误 ImportError PILKit was unable to import the Python Imaging Library Please confirm it s installed and
  • ESP8266+天猫精灵+贝壳物联 简单直接点亮一个LED灯

    本文将介绍如何通过天猫精灵透过贝壳物联来使ESP8266点亮一个灯 如果大家途中遇到什么奇葩问题 请努力移驾各大搜索神器或查看贝壳物联帮助文档解决 正所谓冤有头 本文主要分为以下几个部分哦 硬件部分 软件下载 软件工具和软件固件 固件刷写
  • 网络和网络协议

    一 网络 一 网络的概念 两个不在同一地理位置的主机 通过传输介质和通信协议 实现通信和资源共享 二 网络的发展史 网络的发展史可以追溯到20世纪60年代末期 当时美国国防部高级研究计划署 ARPA 开始研究一种名为ARPANET的计算机网
  • video downloadhelper需要合作应用_Streamlit是python的一个机器学习、数据科学、应用开发框架...

    1 说明 初探 1 1 Streamlit 1 1 1 是一个开源Python库 可轻松构建用于机器学习的漂亮应用程序 1 1 2 是一款专为机器学习工程师创建的免费 开源 app 构建框架 1 1 3 是一个简单而强大的应用程序模型 可让
  • gdb调试教程

    gdb调试是c c 代码调试最重要的工具了 我们今天来系统熟悉一下 太长不看版 注意 如果针对cmake项目 需要把编译模式从release改成debug 否则无法定位到准确的行数 进入gdb debugger界面 gt gdb filen