< 返回版块

wuya 发表于 2023-01-05 20:26

Tags:TryFromIntError;fmt;Debug

我通过nm生成ELF文件发现TryFromIntError的Debug::fmt有被调用,无法确定是哪里调用产生的,请问有什么办法可以知道是调用哪个函数产生的。目前查看了所有的unwrap操作,没有涉及Result<T, TryFromIntError>。

080036c5 000000e8 t <core::num::error::TryFromIntError as core::fmt::Debug>::fmt

评论区

写评论
作者 wuya 2023-01-06 19:21

原因已找到:调用Result<(),()>::unwrap()导致,但是没有找到TryFromIntError产生的地方,()的Debug::fmt只是pad了一个"()":

impl Debug for () {
    #[inline]
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        f.pad("()")
    }
}

unwrap的操作最终调用panic!,不清楚是否是编译器生成的代码搞的

作者 wuya 2023-01-06 13:10

实际运行并没有触发这个Error,我是通过nm查看ELF文件的符号表看到有这个函数依赖。

我已经通过注释代码找到了调用函数:Err(()).unwrap(),还没有具体看这个Error的Debug实现,把这个unwrap操作去掉TryFromIntError::fmt的依赖就没有了

--
👇
苦瓜小仔: RUST_BACKTRACE=1 cargo r 看 stack backtrace 也不行吗

苦瓜小仔 2023-01-06 12:05

RUST_BACKTRACE=1 cargo r 看 stack backtrace 也不行吗

作者 wuya 2023-01-05 21:43
  • 通过lld的--cref参数生成的map文件里面没有包含调用信息,所以也没法知道调用源地址
  • 通过--track-symbol参数cargo编译的时候没有打印lld的标准输出信息,所以也没法确认
作者 wuya 2023-01-05 21:39

在我的代码里面没有发现直接生成TryFromIntError的地方

作者 wuya 2023-01-05 21:37

我是想找到是哪个函数调用了Debug::fmt(TryFromIntError),不是由我直接调用的,但是有可能是我间接调用某个函数引入的。目前已知Result<T,TryFroTryFromIntError>.unwrap会调用,但是这个Result是哪里产生的我就不知道了,有可能是core库里面调用的,也有可能不是unwrap引入的

--
👇
苦瓜小仔: 你需要自己做错误处理。

对于一个基础函数:

fn f() -> Result<u8, std::num::TryFromIntError> {
    u8::try_from(-1i8)
}

如果仅仅是转发错误,你只会得到最初的错误信息:

fn main() -> anyhow::Result<()> {
    f()?;
    Ok(())
}

打印:Error: out of range integral type conversion attempted

你觉得打印的错误没什么用处,因为没有你想看到的信息。如果你对错误发生的地点感兴趣,可以这样写

use anyhow::Context;
fn g() -> anyhow::Result<u8> {
    u8::try_from(-1i8).with_context(|| {
        format!("{}:{}", file!(), line!())
    })
}

那么会得到

Error: src/main.rs:15

Caused by:
    out of range integral type conversion attempted

嗯,你想要知道的任何错误信息,都需要类似地做错误处理。

此外你还可以直接使用 eyre

fn h() -> eyre::Result<u8> {
    Ok(u8::try_from(-1i8)?)
}

那么直接得到

Error: out of range integral type conversion attempted

Location:
    src/main.rs:23:8
苦瓜小仔 2023-01-05 21:00

你需要自己做错误处理。

对于一个基础函数:

fn f() -> Result<u8, std::num::TryFromIntError> {
    u8::try_from(-1i8)
}

如果仅仅是转发错误,你只会得到最初的错误信息:

fn main() -> anyhow::Result<()> {
    f()?;
    Ok(())
}

打印:Error: out of range integral type conversion attempted

你觉得打印的错误没什么用处,因为没有你想看到的信息。如果你对错误发生的地点感兴趣,可以这样写

use anyhow::Context;
fn g() -> anyhow::Result<u8> {
    u8::try_from(-1i8).with_context(|| {
        format!("{}:{}", file!(), line!())
    })
}

那么会得到

Error: src/main.rs:15

Caused by:
    out of range integral type conversion attempted

嗯,你想要知道的任何错误信息,都需要类似地做错误处理。

此外你还可以直接使用 eyre

fn h() -> eyre::Result<u8> {
    Ok(u8::try_from(-1i8)?)
}

那么直接得到

Error: out of range integral type conversion attempted

Location:
    src/main.rs:23:8
作者 wuya 2023-01-05 20:52

代码运行没有触发这个Error,我是想找到调用地方,删掉这个调用

--
👇
shanliu: 把调用堆栈打出来不就找到了

shanliu 2023-01-05 20:47

把调用堆栈打出来不就找到了

作者 wuya 2023-01-05 20:30

查找了core库的代码,涉及TryFromIntError的都是usize和其他基础int类型的转换,这些TryFrom操作不清楚会在什么操作下被调用到

1 共 10 条评论, 1 页