< 返回版块

eweca-d 发表于 2021-03-21 23:00

有如下闭包(不必要的部分和公式部分已简化):

fn solver(u: i32) {
    let func_k = move |disp: f64| {
        let g1 = (u / 100) as f64;
        let gu = disp / 0.01;
        let g12 = g1 * g1;
        let gu2 = gu * gu; 
        (g12 * (g12 + gu2).powf(-1.5) - 1.0)
    };
    let mut model = model::new().set_k_func(func_k);
}

impl model {
    pub fn set_k_func(&mut self, Box<dyn Fn(f64) -> f64>) -> &mut self {
    // --snip-- //
    }
}

直接跳出错误:error:xxxxxxxx(exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

而把变量g1的表达式改为let g1 = u as f64 / 100.0则可以正常算出结果。我就有点纳闷了,变量u不是被我move进闭包了,这两个式子看起来效果应该是一样的啊?为什么会有这种奇怪的错误?

是我想错了,由于错误的使用了整数除法,导致g1=0,然后在gu=0时,(g12 + gu2).powf(-1.5) = NaN出现了数据NaN,导致了后来的错误。

评论区

写评论
作者 eweca-d 2021-03-22 17:00

我从C++那里编译了一个Eigen的求解稀疏矩阵的函数作为动态库来给rust用,NaN由于某种我不知道的原因在这个动态库里access violation了。个人猜测大概是eigen特性或者是FFI时候的冲突,总之,我这个动态库貌似只要传入的数据里带有NaN,就会触发access violation。

--
👇
Aya0wind: 你在safe rust里,没有使用外部库的地方出现access violation? 如果真是你摆出的这段代码的问题,那你可以去提交bug了,否则建议查一查你没放出来的那部分代码,特别是带unsafe的。 还有先转浮点再除以100和先除以100再转浮点那可完全不一样,你的u是个整数,除以100的结果还是整数,小数部分就没了。所以我觉得问题并不在闭包这。

作者 eweca-d 2021-03-22 16:51

你是对的,我仔细排查了下。是我想错了,是你说这个问题。实际想要的是1.0/100.0 = 0.01,出错的代码是(1 / 100) as f64 = 0,然后后来再powf(-1.5)之类的出来的是NaN,导致了后来的错误。感谢。

--
👇
Aya0wind: 你在safe rust里,没有使用外部库的地方出现access violation? 如果真是你摆出的这段代码的问题,那你可以去提交bug了,否则建议查一查你没放出来的那部分代码,特别是带unsafe的。 还有先转浮点再除以100和先除以100再转浮点那可完全不一样,你的u是个整数,除以100的结果还是整数,小数部分就没了。所以我觉得问题并不在闭包这。

w 2021-03-22 10:29

试了一下没有问题


rustc 1.50.0 (cb75ad5db 2021-02-10)

chinagxwei 2021-03-22 09:54

测试了一下,除了闭包没有用Box包裹报错以外,并没有大问题。加上Box后运行正常。并未出现你发出的错误。

Aya0wind 2021-03-22 09:34

你在safe rust里,没有使用外部库的地方出现access violation? 如果真是你摆出的这段代码的问题,那你可以去提交bug了,否则建议查一查你没放出来的那部分代码,特别是带unsafe的。 还有先转浮点再除以100和先除以100再转浮点那可完全不一样,你的u是个整数,除以100的结果还是整数,小数部分就没了。所以我觉得问题并不在闭包这。

1 共 5 条评论, 1 页