【问题标题】:How do you track the source of an error?您如何跟踪错误的来源?
【发布时间】:2015-07-07 18:03:02
【问题描述】:

对于恐慌,RUST_BACKTRACE=1 非常有用,但它对于非致命错误的作用不大。

例如,我有一些以

结尾的代码
match res {
    Ok(()) => (),
    Err(_) =>
        println_err!("{:?}", res),
}

不幸的是,默认情况下,在gdb 中运行并不会做很多事情,因为没有发生任何异常情况。 (在默认情况下,未处理的异常会调用 abort()gdb 会在 SIGABORT 上中断的旧 C++ 行为非常方便。)

接下来,由于gdb现在支持反向执行,我想我可以通过在println_err行设置断点并反转直到找到错误源来调试它。

(gdb) reverse-step
Target multi-thread does not support this command.

快速搜索显示我应该做类似的事情

(gdb) set libthread-db-search-path /etc/nonexistent
(gdb) start

然后我明白了

(gdb) reverse-step
Target child does not support this command.

这是否意味着 Rust 不支持反向调试?还是我做错了什么/次优?

有没有比手动检查每个转发错误的函数(使用try!())来找出它的来源更好的解决方案?

编辑:利用手动断点并重新启动,我到达了函数返回的地步,但 GDB 似乎无法判断返回值是什么:

(gdb) finish
Run till exit from #0  cafs::reader::Reader::read_rawblock (self=0x7fffffffd628, h=Sha256 = {...}) at src/reader.rs:90
0x00005555556a096b in cafs::reader::Reader::read_blockref_vec (self=0x7fffffffd628, r=Reader = {...}) at src/reader.rs:101
101             let raw = try!(self.read_rawblock(h));
Value returned is $3 = {union Result<collections::vec::Vec<u8>, std::io::error::Error> (struct Reader *, struct Sha256)} 0x0
(gdb)

所以,也许 GDB 不会那么有用...

【问题讨论】:

    标签: debugging gdb rust


    【解决方案1】:

    反向调试不像reverse-step那么简单。您必须在失败前的某个时间停下来,然后向 gdb 询问record。然后在稍后的某个时间点你可以反转。

    内置的记录工具速度较慢。而且,它不支持多线程。除了一些小的用例之外,很难推荐它。

    如果你真的想针对这个问题进行反向调试,让我推荐rr-project。这是解决此问题的更好方法。

    【讨论】:

    • 鉴于 GDB 明显无法理解 Rust 返回值,我认为这不再是可行的方法。我正在尝试反向调试,因为当我在ocamldebug 中使用它时效果非常好。
    【解决方案2】:

    如果您想使用Result&lt;T, E&gt; 进行堆栈跟踪,您可以构建一个执行此操作的类型:http://phildawes.net/blog/2015/06/17/rust-stacktrace/

    【讨论】:

    • 这将产生一个跟踪到错误首先在我的代码中被转换的位置。这当然是某种东西,但我更愿意看看它起源于产生它的图书馆的哪里。如果我可以让gdb 在那里中断,那将是真的很好,这样我就可以检查状态,而不仅仅是获取回溯。
    • 顺便说一句,我在 Reddit 上看到的类似替代方案是 rust-throw。 github.com/daboross/rust-throw
    猜你喜欢
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-03
    • 2019-12-01
    • 1970-01-01
    相关资源
    最近更新 更多