繁体   English   中英

__rust_begin_short_backtrace 在 Rust 中如何工作?

[英]How does __rust_begin_short_backtrace work in Rust?

如题。

我知道__rust_begin_short_backtrace用于堆栈回溯,但它实际上是如何工作的? 我发现它的实现真的很短,就像下面一样。 它所做的只是间接调用传入的 function,并返回结果。 我还发现对应的 function __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()
});

Rust 正在插入这些“虚拟符号”以允许短回溯。

考虑这段代码

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 会扫描堆栈以__rust_end_short_backtrace__rust_begin_short_backtrace函数。

这些函数不做任何事情(因此阻止它们被优化掉的诡计),但是 rust 它们是供回溯器拾取的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM