4. 基本断点

调试这活儿,说白了就是让程序在关键时刻停下来,让你看看它到底在搞什么鬼。而断点,就是我们让程序停下来的那个「刹车」。今天咱们就聊聊 GDB 里最基础的四种断点玩法。

4.1 break 命令:一切断点的起点

GDB 里设置断点的核心命令就是 break,简写为 b。我个人习惯用简写,毕竟调试时敲命令越快越好。

基本语法很简单:

(gdb) break 位置
(gdb) b 位置

这个「位置」可以是行号、函数名,也可以是文件名加行号的组合。咱们一个个来看。

4.2 行号断点:最直观的断点

行号断点是最常用的。你想想看,当你知道某一行代码有问题,直接在那行停住,多直接。

// 示例代码:test.c
#include <stdio.h>

int main() {
    int a = 10;
    int b = 20;
    int c = a + b;  // 我想在这行停住
    printf("c = %d\n", c);
    return 0;
}

设置行号断点:

(gdb) b 7
Breakpoint 1 at 0x4004f6: file test.c, line 7.
(gdb) r
Starting program: /home/user/test

Breakpoint 1, main () at test.c:7
7           int c = a + b;  // 程序停在这里了

嗯,这里要注意:行号是相对于当前源文件的。如果你的项目有多个源文件,可以用 文件名:行号 的格式:

(gdb) b main.c:42
我的小技巧: 设置行号断点前,先用 list 命令看看源代码,确认行号没错。我在项目中遇到过好几次因为行号看错,断点打在空行上的尴尬事。

4.3 函数断点:入口处拦截

函数断点更高级一点。你不需要知道函数在哪一行,只要知道函数名就行。程序每次进入这个函数都会停下来。

(gdb) b main
Breakpoint 1 at 0x400526: file test.c, line 4.
(gdb) b printf
Breakpoint 2 at 0x400430

函数断点有个好处:如果函数被重载了(C++ 里常见),GDB 会列出所有匹配的函数让你选:

(gdb) b myFunction
[0] cancel
[1] all
[2] myFunction(int)
[3] myFunction(double)
> 2
Breakpoint 3 at 0x400567: file test.cpp, line 15.

选 2 就是只在这个 myFunction(int) 版本上设断点。这个功能我在调试 C++ 多态代码时帮了大忙。

4.4 条件断点:精准打击

条件断点是我最喜欢的。说白了就是:只有当某个条件满足时,程序才停下来。这在循环里特别有用。

语法:

(gdb) break 位置 if 条件

举个例子,你有一个循环 1000 次的代码,但只在第 500 次时出问题。你总不能手动按 500 次 continue 吧?

for (int i = 0; i < 1000; i++) {
    process(i);  // 我想在第500次时停住
}

设置条件断点:

(gdb) b 5 if i == 500
Breakpoint 1 at 0x4004f6: file test.c, line 5.

程序运行到第 5 行,且 i == 500 时才会停下。省时省力。

条件断点的威力: 我曾经调试过一个内存泄漏问题,在分配函数上设了条件断点 b malloc if size > 1024,一下子就抓住了那个分配大块内存的罪魁祸首。

4.5 断点的管理

设了断点之后,怎么管理它们?GDB 提供了一套完整的断点管理命令:

命令 作用
info breakpoints 列出所有断点
disable 编号 禁用某个断点(不删除)
enable 编号 启用某个断点
delete 编号 删除某个断点
clear 行号 删除某行的断点

我个人习惯用 disable 而不是 delete。因为有时候你只是暂时不想用这个断点,后面可能还会用到。删了还得重新设,麻烦。

避坑指南: 我曾经在调试一个大型项目时,设了十几个断点,结果忘了哪些是干什么的。后来我养成了给断点加注释的习惯:b main.c:42 if x > 10 # 检查边界条件。虽然 GDB 不直接支持注释,但你可以用 comment 命令给断点加描述。

4.6 知识体系图

下面这张图帮你理清今天讲的内容:

GDB 基本断点知识体系 break 命令 行号断点 b 行号 函数断点 b 函数名 条件断点 b 位置 if 条件 断点管理 info/disable/enable/delete 四种断点各有用途,组合使用效果更佳

四种断点各有各的适用场景。行号断点适合精确位置,函数断点适合入口拦截,条件断点适合循环和特定条件。实际调试时,我经常把它们组合起来用,效果出奇的好。

好了,断点的基本用法就这些。记住一点:断点不是越多越好,而是越精准越好。设太多断点反而会让你迷失在调试的海洋里。

可可精品资料库