在 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();
}
}
您不应该使用
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
相当透明,因此函数内的实现不应发生(太大)变化。