【问题标题】:How do I make the debugger break when an exception is thrown in D?当在 D 中引发异常时,如何使调试器中断?
【发布时间】:2018-04-24 21:38:33
【问题描述】:

当调试由于未捕获的异常而失败的 D 代码时,异常机制会一直展开堆栈,然后打印堆栈跟踪,给我们留下一些帮助不大的信息:

(gdb) bt
No stack.

堆栈跟踪为我们提供了引发异常的行,但如果它直到几千次迭代才抛出,这并不是特别有用。能够将调试器设置为在抛出异常时的异常点。

目前,关于这方面的唯一文档似乎是 dlang 邮件列表上的一些帖子。我找到了一些适用于我的设置的方法,并将它们包含在我自己的答案中,但是为了其他有这个问题的人的利益,我希望我们能得到一个更全面的答案,其中包含任何组合的方法{ dmd, gdc, ldc } x { gdb, lldb }。

【问题讨论】:

  • 真正让我吃惊的是,有一个简单的解决方案可以设置一个内部变量,因此所有未捕获的异常都被调试器捕获,捕获的异常正常工作,适用于所有调试器、所有编译器、所有操作系统只需将命令行参数传递给您运行的程序......但他们从未合并 PR,尽管它似乎没有任何问题。 github.com/dlang/druntime/pull/2035
  • @AdamD.Ruppe 如果他们要求 _d_throw 在所有实现中必须以该名称存在,那就更好了,因为它不需要重新编译。但如果不出意外,您的 rt_trapExceptions hack 为我们提供了与 ldc 一起使用的 一些东西。
  • 但是您实际上并不想中断 _d_throw,即使它存在,因为它会中断所有抛出的异常,包括程序中捕获的异常。 trapExceptions 的美妙之处在于它只捕获 uncaught 异常,因此您不必一直告诉它继续处理普通的、已处理的情况。 (有时候你希望它在投掷时打破,但你可以在投掷的特定线上打破而不是在所有静止)

标签: debugging gdb d lldb


【解决方案1】:

因为DMD/DRuntime 2.082.0 这可以通过将--DRT-trapException=0 标志传递给您的程序来实现。 Adam 在 cmets 中链接的 PR 已为此合并。

通过该添加,您还可以使用比rt_trapExceptions 代码更漂亮的解决方案在代码中强制使用它:

extern(C) __gshared string[] rt_options = [ "trapExceptions=0" ];

您可以在此处阅读有关配置运行时选项的更多信息:https://dlang.org/phobos/rt_config.html


在此之前,您可以在自定义 main 中设置 rt_trapExceptions,如 This Week in D: August 7, 2016 中所述:

extern extern(C) __gshared bool rt_trapExceptions;
extern extern(C) int _d_run_main(int, char**, void*);

extern(C) int main(int argc, char** argv) {
    rt_trapExceptions = false;
    return _d_run_main(argc, argv, &_main);
}

int _main() {
    // your code here
}

【讨论】:

    【解决方案2】:

    所有这些都在 Linux 上进行了测试。 -g 标志被传递给所有三个编译器。 -d-debug 标志也被传递给 ldc,尽管它做了很多好事。

    gdb

    (gdb) 打破 _d_throwdwarf

    • 适用于 linux + dmd
    • 不适用于 linux + gdc
    • 不适用于 linux + ldc

    (gdb) 中断_d_throwc

    • 未知,但运行时源似乎表明这是 _d_throwdwarf 用于 win32 和 win64。有 Windows 系统的人想测试一下吗?

    (gdb) 中断对象.Throwable.this

    • 适用于 linux + dmd
    • 适用于 linux + gdc
    • 不适用于 linux + ldc

    (gdb) 捕捉抛出|捕捉|信号

    • 不适用于 linux + dmd 或 linux + gdc

    lldb

    (lldb) b _d_throwdwarf

    • 适用于 linux + dmd

    【讨论】:

    • 上面所有的符号断点方法都应该像使用 gdb 一样使用 lldb (除了你会使用 b <symbol_name> 或 break set -n <symbol_name>。lldb 目前没有任何语言支持 D 所以异常断点不支持 D 异常。
    • @JimIngham b _d_throwdwarf 如果它是用 dmd 编译的(添加到列表中;谢谢),但 b object.Throwable.this 在所有编译器中都“无法解析位置”。
    • 什么是object.Throwable.this?这看起来不像 C 或 C++ 符号名称。
    • @JimIngham dmd 或 gdc 下编译时所有异常都会调用的函数。 (我还尝试了b object::Throwable::this,以防不同的语法导致 lldb 关闭,结果相同。)
    • 所以这个东西是D符号? D 是否有一些名称修改方案?如果是这样,那么要设置断点,lldb 必须知道如何将 D 语法名称转换为实际的损坏符号名称(它目前不能这样做,因为它对 D 一无所知)。但是,如果你能找出实际的符号名称(如 nm 或任何你最喜欢的符号转储器所示),那么你应该能够破解那个损坏的名称。
    猜你喜欢
    • 1970-01-01
    • 2014-07-23
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    相关资源
    最近更新 更多