2

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 u8 type

  • Testing 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();
    }
}
3
  • This needs a lot more information to answer. This crosses the boundary between programming languages so the interface between them is of utmost importance and is also easy to get wrong. So please show how you are loading and calling the Rust code from Java. Commented Sep 4, 2023 at 1:59
  • ok, I will update my question to clarify how I am using Rust from Java. Commented Sep 4, 2023 at 1:59
  • I have updated my question to include more details about how I am referencing the native code from the JVM Commented Sep 4, 2023 at 2:10

1 Answer 1

5

You should not use Box to handle memory you got from the Java side. Box will attempt to deallocate the memory when it goes out of scope, but that will encounter errors since the memory was not allocated by Box initially.

Instead use the slice only:

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));

And any other code you omitted that uses it. The implementations within the functions should not change (much) since Box is fairly transparent.

Sign up to request clarification or add additional context in comments.

1 Comment

This worked very well for me! I did not understand the deallocation logic, but I do now. Thank you so much! Have a great one

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.