为什么 Rust 原生库在调用函数时会随机崩溃?

问题描述 投票:0回答:1

在 Rust 中,我有一个压缩数组的函数:

fn create_bitvec(data: Box<[u8]>) -> [u8; 49152] {
    let mut bit_vector = [0u8; 49152];
    for (index, &value) in data.iter().enumerate() {
        let byte_index = (index * 4) / 8;
        let bit_index = (index * 4) % 8;
        let value_mask = 0b00001111 << bit_index;
        let shifted_value = (value << bit_index) & value_mask;
        bit_vector[byte_index] &= !value_mask;
        bit_vector[byte_index] |= shifted_value;
    }
    debug!("made it here. {:?}", bit_vector);
    bit_vector
}

(抱歉,如果函数的实现不好,但这不是这里的具体问题)。

该函数的使用方式如下:

pub fn create(data: Box<[u8]>) -> Chunk {
    assert_eq!(data.len(), FULL, "Data length doesn't match!");
    let bitvec = Chunk::create_bitvec(data);
    debug!("Got here 1!");
    let c = Chunk {
        data: Chunk::create_rle(bitvec),
    };
    debug!("Got here 2: {:?} {}!", c.data, c.data.len());
    c
}

该程序用作 Java 的本机库。该结构体不直接使用,但仅使用

extern "C" fn
中的
lib.rs
公开了一些关键功能。当从 rust 调用 create 作为单元测试的一部分时,一切都按预期工作,但是当从 JVM 使用时,程序崩溃,没有额外的恐慌/调试信息,并退出代码
-1073740940 (0xC0000374)
。我根本无法理解的真正令人困惑的部分是
made it here
被记录得很好,并且具有正确的数组,但程序在
Got here 1
被记录之前崩溃了。以下是我已经尝试过的一些事情:

  • 验证数组长度

  • 验证数据是否适合

    u8
    类型

  • 仅测试 Rust 代码

我怀疑这个问题可能与内存有关,但我不确定,特别是因为我将

Xmx8G
传递给了 JVM。

我正在为当地人使用

jnr-ffi

这是来自

lib.rs
的相关 Rust 代码:

static CHUNK_STATE: Mutex<Cell<Option<ChunkManager>>> = Mutex::new(Cell::new(None));
#[no_mangle]
pub extern "C" fn chunk_build(x: i64, y: i64, arr: *const u8) {
    info!("Building chunk: {}, {}", x, y);
    unsafe {
        CHUNK_STATE.lock().get_mut().as_mut().expect("Not initialized!").build((x, y), Box::from_raw(slice::from_raw_parts_mut(arr as *mut u8, WIDTH * WIDTH * HEIGHT)));
    }
}

以及 Java 中的用法:

public interface NativeLib {
    void chunk_build(int x, int y, byte[] arr);
}
import jnr.ffi.LibraryLoader;

public class Natives {
    public static NativeLib INSTANCE;

    public static void init() {
        INSTANCE = LibraryLoader.create(NativeLib.class).load("C:\\Users\\*\\*\\*\\nativelib\\target\\release\\pathlib.dll");
        INSTANCE.init();
    }
}
java rust crash jnr
1个回答
0
投票

您不应该使用

Box
来处理从 Java 端获得的内存。当内存超出范围时,
Box
将尝试释放内存,但这会遇到错误,因为内存最初不是由
Box
分配的。

只使用切片:

fn create_bitvec(data: &[u8]) -> [u8; 49152] {
    // ...
}

pub fn create(data: &[u8]) -> Chunk {
    // ...
}
.build((x, y), slice::from_raw_parts_mut(arr as *mut u8, WIDTH * WIDTH * HEIGHT));

以及您省略的使用它的任何其他代码。由于

Box
相当透明,因此函数内的实现不应发生(太大)变化。

© www.soinside.com 2019 - 2024. All rights reserved.