In Rust, I have a function that compresses an array:
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
}
(sorry if the implementation of the function is bad, but that's not the specific problem here).
The function is used like this:
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
}
This program is used as a native library for Java. The struct is not directly used, but only some crucial functions are exposed using extern "C" fn from lib.rs. When calling create from rust as part of a unit test, everything works as expected, but when used from the JVM, the program crashes with no additional panic/debug info, with exit code -1073740940 (0xC0000374). The really confusing part that I simply cannot wrap my head around is that made it here gets logged just fine, with the correct array, but the program crashes before Got here 1 can be logged. Here are some things I have already tried:
Verifying the array length
Verifying the data fits under the
u8typeTesting the code from only Rust
I suspect the issue may have something to do with memory, but I am not sure, especially since I passed Xmx8G to the JVM.
I am using jnr-ffi for the natives.
Here is the relevant rust code from lib.rs:
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)));
}
}
And its usage from 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();
}
}