上篇文章:Linux:版本控制器Git(第一章)|历史|理解Git|相关git操作|提交冲突解决
目录
[2.4set var确定问题原因](#2.4set var确定问题原因)
前言
在之前与Linux系统相关的文章中,已经深度了解了下载,编译,自动化,Git等内容,这节接着了解与学习调试相关的内容。
1.什么样的程序才能调试
1.1示例
Makefile:
1 cmd.exe:mycmd.c
2 gcc -o $@ $^
3 .PHONY:clean
4 clean:
5 rm -f cmd.exe
mycmd.c:
#include <stdio.h>
int Sum(int s, int e)
{
int result = 0;
int i = s;
for(; i <= e; i++)
{
result += i;
}
return result;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
printf("running done, result is: [%d-%d]=%d\n", start, end, n);
return 0;
}
结果,此代码没有调试信息:

小常识:
程序通常有两种主要的构建配置:Debug和Release。在开发周期中,存在多个不同的版本供不同角色使用,其中在开发和测试构建中,通常基于Debug配置,在预发布构建中会对基于Release配置构建的版本进行最终验收测试。
而通过gcc,g++在编译程序时,默认是通过release方式发布的:

要将其改为debug版本需要修改Makefile:
1 cmd.exe-debug:mycmd.c
2 gcc -o $@ $^ -g
3 .PHONY:clean
4 clean:
5 rm -f cmd.exe
-g:给形成的可执行程序内部,添加可调式信息。
结果:

2.gdb/cgdb相关操作
2.1了解cgdb
启用调试之后,我们发现下图的调试操作界面并不友好:

Cgbd分屏操作 ESC 进⼊代码屏, i 回到 gdb 屏
因此我们使用cgdb进行相关调试操作:
安装cgdb命令:
sudo yum / apt install -y cgdb


2.2常见使用命令
开始:gdb xxx
退出:ctrl + d 或 quit
| 命令 | 作用 | 样例 |
|---|---|---|
| list / l | 显示源代码,从上次位置开始,每次列出10行 | list / l 10 |
| list / l 函数名 | 列出指定函数的源代码 | list / l main |
| list / l 文件名:行号 | 列出指定文件的源代码 | list / l mycmd.c:1 |
| r / run | 从程序开始连续执行 | run |
| n / next | 单步执行,不进入函数内部(逐过程) | next |
| s / step | 单步执行,进入函数内部(逐语句) | step |
| break / b [文件名:]行号 | 在指定行号设置断点 | break 10 / break test.c:10 |
| break / b 函数名 | 在函数开头设置断点 | break main |
| info break / b | 查看当前所有断点的信息 | info break |
| finish | 执行到当前函数返回,然后停止 | finish |
| print / p 表达式 | 打印表达式的值 | print start+end |
| p 变量 | 打印指定变量的值 | p x |
| set var 变量=值 | 修改变量的值 | set var i=10 |
| continue / c | 从当前位置开始连续执行程序 | continue |
| delete / d breakpoints | 删除所有断点 | delete breakpoints |
| delete / d breakpoints n | 删除序号为 n 的断点 | delete breakpoints 1 |
| disable breakpoints | 禁用所有断点 | disable breakpoints |
| enable breakpoints | 启用所有断点 | enable breakpoints |
| info / i breakpoints | 查看当前设置的断点列表 | info breakpoints |
| display 变量名 | 跟踪显示指定变量的值(每次停止时) | display x |
| undisplay 编号 | 取消对指定编号的变量的跟踪显示 | undisplay 1 |
| until X行号 | 执行到指定行号 | until 20 |
| backtrace / bt | 查看当前执行栈的各级函数调用及参数 | backtrace |
| info / i locals | 查看当前栈帧的局部变量值 | info locals |
| quit | 退出 GDB 调试器 | quit |
断点的本质:区域化的执行->找到问题:查找问题,二分查找确定问题的范畴。是一个工具。
断点是可以被"使能" enable 或 disable的
disable/enable示例


r/n/s/display示例
类似于vs中的监视操作:

p/until示例
注意:until不能在不同函数中跳转,不能执行空行,并且只能向下跳

finish示例

bt示例

info示例

2.3watch
执行时监视一个表达式的值,如果监视的表达式在程序运行期间的值发生变化,GDB会暂停程序的执行,并通知使用者。常用于检测指针

如下:

2.4set var确定问题原因
可以直接更改相关错误
// mycmd.c
#include <stdio.h>
int flag = 0; // 故意错误
//int flag = -1;
//int flag = 1;
int Sum(int s, int e)
{
int result = 0;
for(int i = s; i <= e; i++)
{
result += i;
}
return result*flag;
}
int main()
{
int start = 1;
int end = 100;
printf("I will begin\n");
int n = Sum(start, end);
printf("running done, result is: [%d-%d]=%d\n", start, end, n);
return 0;
}
(gdb) p result
$1 = 5050
(gdb) p flag
$2 = 0
(gdb) set var flag=1 # 更改flag的值,确认是否是它的原因
(gdb) p flag
$3 = 1
(gdb) n
17 }
(gdb) n
main () at mycmd.c:25
25 printf("running done, result is: [%d-%d]=%d\n", start, end,
n);
(gdb) n
running done, result is: [1-100]=5050 # 是它的原因
26 return 0;
2.5条件断点
2.5.1添加条件断点


2.5.2给已经存在的断点新增条件

本章完。