标题是。
我知道__rust_begin_short_backtrace用于堆栈回溯,但是它实际上是如何工作的呢?我发现它的实现真的很短,如下所示。它所做的只是间接调用传入函数,并返回结果。我还发现对应函数__rust_end_short_backtrace具有完全相同的实现。代码在library/std/src/sys_common/backtrace.rs.
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that
/// this is only inline(never) when backtraces in libstd are enabled, otherwise
/// it's fine to optimize away.
#[cfg_attr(feature = "backtrace", inline(never))]
pub fn __rust_begin_short_backtrace<F, T>(f: F) -> T
where
F: FnOnce() -> T,
{
let result = f();
// prevent this frame from being tail-call optimised away
crate::hint::black_box(());
result
}相关实现的另一部分也在"library/std/src/sys_common/backtrace.rs".上。下面是这个部分的代码片段,我认为这些代码具有高度的相关性和重要性,但我不理解Rust如何处理与前两个函数相关的符号的逻辑:
backtrace_rs::trace_unsynchronized(|frame| {
if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES {
return false;
}
let mut hit = false;
let mut stop = false;
backtrace_rs::resolve_frame_unsynchronized(frame, |symbol| {
hit = true;
if print_fmt == PrintFmt::Short {
if let Some(sym) = symbol.name().and_then(|s| s.as_str()) {
if sym.contains("__rust_begin_short_backtrace") {
stop = true;
return;
}
if sym.contains("__rust_end_short_backtrace") {
start = true;
return;
}
}
}
if start {
res = bt_fmt.frame().symbol(frame, symbol);
}
});
if stop {
return false;
}
if !hit {
if start {
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
}
}
idx += 1;
res.is_ok()
});发布于 2021-05-08 08:51:42
铁锈是插入这些“虚拟符号”,以允许一个简短的回溯。
考虑一下这段代码
fn a() {
b()
}
fn b() {
c()
}
fn c() {
d()
}
fn d() {
panic!()
}
fn main() {
a()
}这给出了一个很好的回溯
$ rustc demo.rs
$ RUST_BACKTRACE=1 ./demo
thread 'main' panicked at 'explicit panic', demo.rs:14:5
stack backtrace:
0: std::panicking::begin_panic
1: demo::d
2: demo::c
3: demo::b
4: demo::a
5: demo::main
6: core::ops::function::FnOnce::call_once
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.如果我们用RUST_BACKTRACE=full
$ RUST_BACKTRACE=full ./demo
thread 'main' panicked at 'explicit panic', demo.rs:14:5
stack backtrace:
0: 0x107e34fe4 - std::backtrace_rs::backtrace::libunwind::trace::ha70d3c0580051b5e
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/../../backtrace/src/backtrace/libunwind.rs:90:5
1: 0x107e34fe4 - std::backtrace_rs::backtrace::trace_unsynchronized::h70c3b3ef22cddd13
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x107e34fe4 - std::sys_common::backtrace::_print_fmt::h698e42c1766250fa
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:67:5
3: 0x107e34fe4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h18cc31b07c2f1a67
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:46:22
4: 0x107e4808d - core::fmt::write::h24f8349e8e89c9af
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/fmt/mod.rs:1096:17
5: 0x107e33046 - std::io::Write::write_fmt::hc54d7d6e95b15753
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/io/mod.rs:1568:15
6: 0x107e36b79 - std::sys_common::backtrace::_print::h07ca439149358748
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:49:5
7: 0x107e36b79 - std::sys_common::backtrace::print::hb7331bf9c4b208ca
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/sys_common/backtrace.rs:36:9
8: 0x107e36b79 - std::panicking::default_hook::{{closure}}::h11b550d560f5cc66
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:208:50
9: 0x107e36709 - std::panicking::default_hook::he168e99d1cf91c3c
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:225:9
10: 0x107e371fb - std::panicking::rust_panic_with_hook::hf87bfc4afef21ea6
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:591:17
11: 0x107e18d27 - std::panicking::begin_panic::{{closure}}::h631923d2be23e79e
12: 0x107e18998 - std::sys_common::backtrace::__rust_end_short_backtrace::h891b6a0b6f9c1b80
13: 0x107e4bcfb - std::panicking::begin_panic::hd2dfddb0fed650c0
14: 0x107e18aec - demo::d::h9d9ff8ddd5377da5
15: 0x107e18ac9 - demo::c::haceeec3fee4323ba
16: 0x107e18ab9 - demo::b::h4146166847508fc7
17: 0x107e18aa9 - demo::a::h60d47e17615f49c4
18: 0x107e18af9 - demo::main::h60dea0663d4b849d
19: 0x107e18bea - core::ops::function::FnOnce::call_once::hf435db03deecd456
20: 0x107e189cd - std::sys_common::backtrace::__rust_begin_short_backtrace::h936624db758e7870
21: 0x107e194d0 - std::rt::lang_start::{{closure}}::ha060b13a4d59d3f5
22: 0x107e37574 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h0e377e204feaadc3
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/core/src/ops/function.rs:259:13
23: 0x107e37574 - std::panicking::try::do_call::h9c5b8eda90bbe0b7
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:379:40
24: 0x107e37574 - std::panicking::try::he150bdff9d5b30f2
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panicking.rs:343:19
25: 0x107e37574 - std::panic::catch_unwind::h04e9c415c0907892
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/panic.rs:431:14
26: 0x107e37574 - std::rt::lang_start_internal::h86f505dc7de50d93
at /rustc/2fd73fabe469357a12c2c974c140f67e7cdd76d0/library/std/src/rt.rs:51:25
27: 0x107e194a5 - std::rt::lang_start::h9d080ccd85b4c518
28: 0x107e18b22 - _main这是完整的堆栈跟踪。然而,这并不是很有用,因为它的大部分是语言内部。因此,在正常模式下,铁锈扫描堆栈的__rust_end_short_backtrace和__rust_begin_short_backtrace函数。
这些函数什么都不做(因此,诡计阻止它们被优化掉),但是对于后台跟踪器来说,它们是生锈的。
https://stackoverflow.com/questions/67444319
复制相似问题