【问题标题】:Can GDB debug C++ lambdas?GDB 可以调试 C++ lambdas 吗?
【发布时间】:2014-02-14 10:09:01
【问题描述】:

我积极使用 C++ 11 功能。我在 Visual Studio 2013 中创建了依赖 lambda 来运行多个线程的程序(lambda 表示任务,线程接收它必须运行的 lambda 实例)。 Lambda 在静态库中定义并链接在可执行文件中,该可执行文件从该可执行文件创建的线程调用它。 当我尝试使用 GDB 调试此应用程序的 Linux 版本时,看起来 GDB 无法进入包含 lambda 的方法。它不能在这个函数中设置断点,当我尝试进入时,它甚至会进入 lambda 从其主体调用的方法,但是在这些方法中的return 之后它不会进入 lambda 主体,它会进入下一个lambda 调用的方法等。 有没有办法用 GDB 调试 lambdas body?

【问题讨论】:

  • 这里的“方法”是什么意思?该术语在 C++ 中没有明确定义。
  • 我的意思是说method时的非静态对象成员函数。
  • 感谢您的澄清。
  • 刚刚测试,gdb (GNU gdb (GDB) 7.6.1) 可以正确地进入lambda。您使用哪个版本的 GDB?你编译优化,符号剥离?
  • 我使用 CentOS 6.5 附带的 GBD,我认为它是 v7.2。我认为这是问题,但不是 lambda one;我在库中有文件functions.cpp,在应用程序中有文件functions.cpp。当使用此静态库构建的静态库和可执行文件具有完全相同名称的源文件时,GDB 似乎无法工作。当它必须使用库中的functions.cpp 时,它看起来像是尝试使用可执行文件中的functions.cpp。所以,问题不在于 lambda。

标签: c++ c++11 lambda gdb


【解决方案1】:

我以前在堆栈跟踪中看到过它们,所以它至少知道它们。我从来没有尝试过设置一个正常的断点。这有点像 hack,但您可以在 x86(-64) 上使用 asm volatile("int $3"); 在一个(或任何地方)设置断点。

这是一个示例程序:

int main(){
    auto f = [](){
        asm volatile("int $3");
    };
    f();
    return 0;
}

这是它到达断点时的回溯:

#0  0x0000000000400577 in main::{lambda()#1}::operator()() const ()
#1  0x000000000040058d in main ()

【讨论】:

  • 您可以在 MIcrosoft Visual C++ 中使用 DebugBreak()__debugbreak()。这是我知道使用 MSVC2012 在 ARM 上打破 lambda 函数的唯一方法; Microsoft 编译器不支持 ARM 和 x64 处理器上的内联汇编。
  • 我从来没有做过,但对于 x64/ARM,我认为您可以创建一个汇编程序/S 文件,您可以使用您的项目编译该文件,该文件定义了一个函数和自定义程序集。然后你只需调用你的汇编函数。 (你能内联那些函数调用吗?)。
【解决方案2】:

根据我的经验,gdb 不能进入 lambdas ——它只是跳过它们。不仅如此,单步执行 lambda 定义似乎会使 gdb 感到困惑,并且会继续执行当前函数的末尾。但是,您可以在 lambda 中显式放置一个断点,如果您到达该点,您将停止。这显然远非理想。

【讨论】:

  • lambda 可能已经过优化和内联。你关闭优化了吗? (-O0)
【解决方案3】:

进入 Lamba 的 .run() go next/step(跳转初始化)直到以下调用:

std::forward<>(args)(...)

进入这个。它将引导您找到 lambda 正文代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 2011-01-19
    • 1970-01-01
    相关资源
    最近更新 更多