debugging 如何在每次调用函数时访问函数的调用位置?

7ivaypg9  于 2023-10-24  发布在  其他
关注(0)|答案(2)|浏览(119)

我想写一个函数,它可以访问文件和调用它的位置的行号。
它看起来像这样:

fn main() {
    prints_calling_location(); // would print `called from line: 2`
    prints_calling_location(); // would print `called from line: 3`
}

fn prints_calling_location() {
    let caller_line_number = /* ??? */;
    println!("called from line: {}", caller_line_number);
}
w9apscun

w9apscun1#

RFC 2091: Implicit caller location添加了track_caller特性,该特性允许函数访问其调用者的位置。
简短的回答:要获得函数被调用的位置,请将其标记为#[track_caller],并在其主体中使用std::panic::Location::caller
根据这个答案,你的例子看起来像这样:

fn main() {
    prints_calling_location(); // would print `called from line: 2`
    prints_calling_location(); // would print `called from line: 3`
}

#[track_caller]
fn prints_calling_location() {
    let caller_location = std::panic::Location::caller();
    let caller_line_number = caller_location.line();
    println!("called from line: {}", caller_line_number);
}

playground link
更具体地说,函数std::panic::Location::caller有两个行为:

  • 在标记为#[track_caller]的函数中,它返回一个&'static Location<'static>,您可以使用它来查找调用函数的文件、行号和列号。
  • 在一个没有#[track_caller]的函数中,它有一个容易出错的行为,即返回调用它的实际位置,而不是函数被调用的位置,例如:
fn main() {
    oops();
    // ^ prints `line: 8` instead of the expected `line: 2`
}

// note: missing #[track_caller] here
fn oops() {
    println!("line: {}", std::panic::Location::caller().line());
}

playground link

szqfcxe2

szqfcxe22#

使用“隐式调用者位置”的另一种选择(无论出于何种原因,它可能对您不可用/不适合)是用C方式来做事情。即将您的函数隐藏在宏后面。

macro_rules! prints_calling_location {
    () => { 
        let caller_line_number = line!();
        println!("called from line: {}", caller_line_number);
    };
}

fn main() {
    prints_calling_location!(); // prints `called from line: 10`
    prints_calling_location!(); // prints `called from line: 11`
}

playground link

相关问题