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

标签 java rust crash jnr

在 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 的 native 库。该结构体不直接使用,但仅使用 lib.rs 中的 extern "C"fn 公开一些关键函数。当从 rust 调用 create 作为单元测试的一部分时,一切都按预期工作,但是当从 JVM 使用时,程序崩溃,没有额外的 panic /调试信息,退出代码 -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();
    }
}

最佳答案

您不应该使用 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 相当透明,因此函数内的实现不应改变(太多)。

关于java - 为什么 Rust 原生库在调用函数时会随机崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77034733/

相关文章:

java - getValueAt() 方法返回 null

android - 当我单击“onmylocation”按钮时,应用程序崩溃

generics - 使用宏编写 const 泛型枚举组合

iphone - 内存警告但事件字节较小

objective-c - Obj-C:在构建时自动生成的自动布局IB,用于具有固定框架的 View 。

java - Selenium WebDriver - 用于定位输入 + onclick 的 cssselector

java - Java SE : Object: entity. Customer@5e80188f 上的 JPA 不是已知实体类型

java - Hibernate 禁用日志记录

rust - 将枚举与具有切片参数的函数一起使用

rust - 作为函数指针类型 : what is the correct type definition? 的异步函数