RUST_BACKTRACE应该告诉我什么?

老板转速

我的程序恐慌,所以我按照它的建议运行RUST_BACKTRACE=1,我明白了(只是一些片段)。

1: 0x800c05b5 - std::sys::imp::backtrace::tracing::imp::write::hf33ae72d0baa11ed
            at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42

2: 0x800c22ed - std::panicking::default_hook::{{closure}}::h59672b733cc6a455
            at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:351

如果程序出现紧急情况,它将停止整个程序,那么我在哪里可以弄清楚它发生在哪一行呢?

这行告诉我第42行和351行有问题吗?

整个回溯都在这张图像上,我觉得将其复制并粘贴到此处很麻烦。

在此处输入图片说明

我从未听说过堆栈跟踪或反向跟踪。我正在编译警告,但是我不知道什么是调试符号。

卢卡斯(Lukas Kalbertodt)

什么是堆栈跟踪?

如果您的程序出现紧急情况,则说明您遇到了一个错误并想修复它。堆栈跟踪希望在这里为您提供帮助。发生紧急情况时,您想知道发生紧急情况的原因(触发紧急情况的功能)。但是直接引发恐慌的功能通常不足以真正了解正在发生的事情。因此,我们还打印了调用前一个函数的函数……等等。我们回溯所有导致崩溃的函数调用,该恐慌main()(几乎)是被调用的第一个函数。

什么是调试符号?

当编译器生成机器代码时,它几乎只需要为CPU发出指令。问题在于,几乎不可能快速查看一组指令来自哪个Rust函数。因此,编译器可以将其他信息插入可执行文件中,该信息会被CPU忽略,但调试工具会使用该信息。

其中一个重要的部分是文件位置:编译器会在哪一行注释哪个指令来自哪个文件。这也意味着我们以后可以看到定义特定功能的位置。如果没有调试符号,则不能。

在堆栈跟踪中,您可以看到一些文件位置:

1: 0x800c05b5 - std::sys::imp::backtrace::tracing::imp::write::hf33ae72d0baa11ed
        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42

Rust标准库附带调试符号。这样,我们可以看到函数的定义位置(gcc_s.rs第42行)。

如果您在调试模式下(rustccargo build)进行编译,则默认情况下会激活调试符号。但是,如果您以发布模式(rustc -Ocargo build --release)进行编译,则调试符号默认情况下处于禁用状态,因为它们会增加可执行文件的大小,并且...通常对于最终用户而言并不重要。您可以使用Cargo.toml在特定profile部分中调整是否要调试符号debug

这些奇怪的功能是什么?

当您第一次查看堆栈跟踪时,您可能会对所看到的所有奇怪的函数名感到困惑。不用担心,这很正常!你有兴趣在什么的一部分,你的代码引发恐慌,但堆栈跟踪显示的所有功能在某种程度上参与。在您的示例中,您可以忽略前9个条目:这些只是处理紧急情况并生成您所看到的确切消息的函数。

条目10仍然不是您的代码,但可能也很有趣:使用您在使用运算符时会index()函数中触发恐慌最后,条目11显示了定义的功能但是您可能已经注意到,该条目缺少文件位置...上一节介绍了解决方法。Vec<T>[]


堆栈跟踪怎么办?(tl;博士)

  1. 如果尚未激活调试符号(例如,仅在调试模式下进行编译)。
  2. 从忽略任何功能stdcore堆栈跟踪的顶部。
  3. 查看您定义的第一个函数,在文件中找到对应的位置并修复错误。
  4. 如果还没有,请更改所有camelCase函数和方法名称snake_case以遵循社区范围的样式指南。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章