dprintf 与 break + 命令 + continue 之间有什么区别?

2024-04-27

例如:

dprintf main,"hello\n"
run

生成与以下内容相同的输出:

break main
commands
  silent
  printf "hello\n"
  continue
end
run

使用是否有显着的优势dprintf over commands,例如它的速度要快得多(如果是的话为什么?),或者有一些不同的功能?

我认为 dprintf 理论上可能会更快,因为理论上它可以使用某种机制编译和注入代码类似于compile codeGDB命令 https://stackoverflow.com/questions/5480868/how-to-call-assembly-in-gdb/31709579#31709579.

或者它主要是一个方便的命令?

Source

在 7.9.1 源代码中,breakpoint.c:dprintf_command,它定义了dprintf, calls create_breakpoint这也是break_command调用,因此它们似乎都使用相同的底层机制。

主要区别在于dprintf通过dprintf_breakpoint_ops结构体,它有不同的回调并在以下位置初始化initialize_breakpoint_ops.

dprintf存储命令字符串列表,就像commands命令,具体取决于设置。他们是:

  • set at update_dprintf_command_list
  • 后被调用type == bp_dprintf检查里面init_breakpoint_sal
  • 被调用的是create_breakpoint.

当到达断点时:

  • bpstat_stop_status被调用并调用b->ops->after_condition_true (bs);到达断点
  • after_condition_true for dprintf is dprintf_after_condition_true
  • bpstat_do_actions_1运行命令

快速基准测试

loop.c

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    uintmax_t i, j, period, max;
    if (argc > 1) {
        max = strtoumax(argv[1], NULL, 10);
    } else {
        max = 10;
    }
    if (argc > 2) {
        period = strtoumax(argv[2], NULL, 10);
    } else {
        period = 1;
    }
    i = 0;
    j = 0;
    while (1) {
        if (period != 0 && i % period == 0) {
            printf("%ju\n", j);
            j++;
        }
        i++; /* line 25 */
        if (i == max)
            break;
    }
}

编译并运行:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o loop.out loop.c

loop.gdb

b 25
commands
silent
printf "%d\n", i
c
end

基准:

$ time gdb -n -q -batch -ex 'tb 39' -ex run -ex 'compile code printf("hello: %d\n", i)' -ex c -args ./loop.out 10000 0

所以我们看到两者dprintf and commands大大减慢速度,并且dprintf仅比同等产品快一点commands.

我问过有没有办法使用compile code加快速度:GDB编译代码并且执行后不删除注入的代码 https://stackoverflow.com/questions/76233877/gdb-compile-code-and-dont-remove-injected-code-after-execution

在 Ubuntu 22.10、GDB 12.1 上测试。


有两个主要区别。

First, dprintf有一些额外的输出模式,可用于使其以其他方式工作。看help set dprintf-channel,或手册,了解更多信息。我认为这些模式是dprintf作为一个单独的实体添加;尽管它们同时又相当专业,不太可能引起普遍兴趣。

不过更有用的是,dprintf不干扰next。如果您编写断点并使用commands, 进而next超过这样的断点,gdb 会忘记next并表现得好像你已经输入了continue。这是 gdb 脚本语言中长期存在的奇怪现象。dprintf不会遇到这个问题。 (如果您需要普通断点的类似功能,则可以通过 Python 执行此操作。)

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

dprintf 与 break + 命令 + continue 之间有什么区别? 的相关文章

  • 想要持续观察并偶尔检查 gdb 中当前帧之外的变量

    假设我定义了一个名为var在主函数中 我为其设置了一个观察点 然后我输入另一个函数func 此时 观察点可能会被删除 这样我就无法访问该变量了 有什么方法可以让您随时随地保持观察点吗 另外 我知道我可以使用类似的语法print main v
  • gdb 正在跳过行

    我在理解 gdb 时遇到一些问题 我有一个主要功能 我自己写了这个主要功能 这个main中的一些行 调用库中的一些函数 我认为库名称并不重要 但它是tesseract ocr 我在 main 中调用函数的行 构造函数在这里 choiceIt
  • Mac 上的 gdb 7.6 缺少带断言的调用堆栈框架

    当调试断言失败的程序时 我无法在 gdb 中获取调用堆栈 我在 Mavericks 上使用 Homebrew 的 g 4 8 和 gdb usr local bin g 4 8 version g 4 8 GCC 4 8 2 usr loc
  • 在GDB中,如何在程序停止时自动执行命令? (如显示)

    我希望每次程序停止时自动执行一些命令 就像 display 对 x 所做的那样 我怎么做 这是我发现的简单方法 define hook stop commands to be executed when execution stops en
  • GDB 在 macOS Catalina 上冻结

    我在 mac 上运行了 helloworld 来尝试 GDB 但在输入 run 后输出 New Thread 0x1903 of process 69034 然后就什么也没有了 我等了一个小时了 还是没有任何动静 完成认证并禁用startu
  • 如何在 Xcode 4 中从断点操作打印字符串值?

    我有一个断点操作 并且正在使用下拉列表中的 日志 选项 我想打印出字符串 摘要 值 我正在这样做 the person name is p name 但这会打印内存地址 我可以切换到调试器命令选项并执行以下操作 po f name 但后来我
  • GDB - 如何打破“有些东西被写入cout”?

    我想设置一个断点 每次写入内容时都会触发stdout通过cout流 但我无法找到该断点的可能位置 我怎样才能在 gdb 中做到这一点 这是一种依赖于平台的方式 如果您在 x86 64 上并使用 gcc 进行构建 则写入 std cout 会
  • windows下无法使用mingw/gdb在eclipse helios cdt上调试小程序,控制台冻结

    我一直在尝试使用 Eclipse CDT 来做一些 C 示例 我可以使用 run 命令很好地运行它们 但是每当我尝试调试时 控制台窗口就会冻结 我可以输入 但程序不运行不继续了 当我调试时 我在控制台窗口上得到以下输出 没有断点 但由于默认
  • 如何让 GDB 打印 64 位变量?

    我正在使用 GDB 来调试用以下代码组装的代码 nasm felf64 Fdwarf 当我想检查标签符号的值时 比如说 var h dq 1 using print var h GDB 假设该值是 32 位并且只给我最低的 4 个字节 x
  • 警告:可加载部分“my_section”位于 ELF 段之外

    我使用 Cortex R4 的 Arm Compiler v6 9 构建了一个 axf elf 文件 但是 当我使用 Arm MCU Eclipse J link GDB 插件将其加载到目标时 它无法加载我的段的初始化数据 如果我使用 Se
  • 如何使用gdb来探索堆栈/堆?

    谁能给我一个快速概述 给我指出一种检查 C 程序堆栈 和堆 的方法的文档 我认为这应该用 GDB 来完成 但如果有其他更直接的替代方案 那么也应该没问题 Thanks 您可以使用 x 命令转储原始内存 因此 如果您想查看堆栈或堆的位 请尝试
  • 如何在 gdb 中附加进程

    我有一个简单的 C 程序 它分叉一个进程 然后运行一个可执行文件 我想将子进程附加到 gdb 我在控制台中运行主程序并打开另一个控制台来查找子进程的 pid 然后使用以下命令启动 gdb gdb attach 12271 where 122
  • 用于 RHEL 的 gdb-multiarch

    我正在尝试寻找方法来运行gdb 多架构RHEL 中的命令 我已经安装了用于 ARM 处理的 QEMU 模拟器 我想安装GDB进行调试 我能够安装GDB 多体系结构在 Ubuntu 中运行命令成功 sudo apt get GDB multi
  • 将大核心文件转换为“minicore”文件

    如何将核心文件减少到仅线程堆栈 我希望能够运行 gdbthread apply all bt在迷你核心上 仅此而已 我正在处理大型 gt 4GB 多线程 Linux ELF 核心文件 这些文件太大而无法返回进行分析 我见过谷歌断点器 htt
  • 如何在 gdb 中打印长字符串的完整值?

    我想在 GDB 中打印 C 字符串的完整长度 默认情况下它是缩写的 如何强制 GDB 打印整个字符串 set print elements 0 来自GDB手册 https sourceware org gdb onlinedocs gdb
  • GDB可以杀死一个特定的线程吗?

    我正在运行一个应用程序 firefox 我想知道是否可以使用 GDB 附加到进程并杀死特定线程 有没有办法做到这一点 我知道此操作可能会使应用程序崩溃 EDIT 在此调试会话中 ps ax显示firefox pid是1328 gdb App
  • 分离Gdb而不恢复劣质

    Gdb 与任何其他程序一样 并不完美 我时不时会遇到导致当前 Gdb 实例无法使用的错误 此时 如果我有一个调试会话 其中有很多有价值的状态 我希望能够在其上启动一个新的 Gdb 会话 也就是说 分离 退出 Gdb 并启动一个新的 Gdb
  • GDB/bin/bash 无法在 Eclipse CDT 中执行应用程序?

    在 Mac OS X Mojave 上使用 Eclipse CDT 运行 GDB 时遇到困难 当我尝试调试项目时 GDB 表现得很混乱 我能够调试几次 但随后它在下一个调试会话开始时开始停止 并显示消息 配置 GDB 可执行文件是 User
  • 从命令输出中设置 GDB 中的环境变量

    我试图在挑战中利用缓冲区溢出 缓冲区从环境变量中获取其值 在 GDB 中 我知道您可以使用以下命令设置环境变量 set environment username test 但是我需要传递用户名变量特殊字符 所以我需要执行以下操作 set e
  • Eclipse 调试模式下的 GDB 找不到 stdlib/rand.c

    我试图让 gdb 在 ubuntu 上与 eclipse cdt 一起运行 以开始调试一些简单的程序 所以我做了我认为必要的步骤来让它运行 1 创建可执行项目 2 Compile 3 Run 4 创建文件 gdbinit 并将其放在主项目文

随机推荐