c_slice::Box immediately gets dropped in safer-ffi

use ::safer_ffi::prelude::*;
#[ffi_export]
pub fn test(boxed_slice_ref: &mut c_slice::Box<u8>) {
    let bytes: Vec<u8> = vec![0, 0, 0, 0];
    let boxed: Box<[u8]> = bytes.as_slice().into();
    *boxed_slice_ref = boxed.into();
}

For some reason, the boxed slice gets dropped immediately when I test this on the C side. I could not figure out a way to reproduce the bug on the Rust side. Here is some output from gdb for a test program:

(gdb) where
#0  0x00007ffff7dd564c in ?? () from /usr/lib/libc.so.6
#1  0x00007ffff7d85958 in raise () from /usr/lib/libc.so.6
#2  0x00007ffff7d6f53d in abort () from /usr/lib/libc.so.6
#3  0x00007ffff7dc97ee in ?? () from /usr/lib/libc.so.6
#4  0x00007ffff7ddf3dc in ?? () from /usr/lib/libc.so.6
#5  0x00007ffff7de122c in ?? () from /usr/lib/libc.so.6
#6  0x00007ffff7de3ba3 in free () from /usr/lib/libc.so.6
#7  0x00007ffff7f40467 in alloc::alloc::dealloc ()
    at /rustc/70f8737b2f5d3bf7d6b784fad00b663b7ff9feda/library/alloc/src/alloc.rs:113
#8  alloc::alloc::{impl#1}::deallocate (self=0x7fffffffcbb8, ptr=..., layout=...)
    at /rustc/70f8737b2f5d3bf7d6b784fad00b663b7ff9feda/library/alloc/src/alloc.rs:250
#9  0x00007ffff7f40211 in alloc::alloc::box_free<[u8], alloc::alloc::Global> (ptr=..., alloc=...)
    at /rustc/70f8737b2f5d3bf7d6b784fad00b663b7ff9feda/library/alloc/src/alloc.rs:348
#10 0x00007ffff7f3f750 in core::ptr::drop_in_place<alloc::boxed::Box<[u8], alloc::alloc::Global>> ()
    at /rustc/70f8737b2f5d3bf7d6b784fad00b663b7ff9feda/library/core/src/ptr/mod.rs:490
#11 0x00007ffff7f3f479 in core::mem::drop<alloc::boxed::Box<[u8], alloc::alloc::Global>> (_x=...)
    at /rustc/70f8737b2f5d3bf7d6b784fad00b663b7ff9feda/library/core/src/mem/mod.rs:979
#12 0x00007ffff7f3d1be in safer_ffi::slice::{impl#24}::drop<u8> (self=0x7fffffffce50)
    at /home/b/.cargo/registry/src/github.com-1ecc6299db9ec823/safer-ffi-0.0.10/src/slice.rs:209
#13 0x00007ffff7f3d12b in core::ptr::drop_in_place<safer_ffi::slice::slice_boxed<u8>> ()
    at /rustc/70f8737b2f5d3bf7d6b784fad00b663b7ff9feda/library/core/src/ptr/mod.rs:490
#14 0x00007ffff7f3da8c in saferffi_test::_::test::{closure#0} () at src/lib.rs:6
#15 0x00007ffff7f3db77 in saferffi_test::_::test (boxed_slice_ref=0x7fffffffce50)
    at /home/b/.cargo/registry/src/github.com-1ecc6299db9ec823/safer-ffi-0.0.10/src/ffi_export.rs:146
#16 0x00005555555551ef in some_test_fn ()
#17 0x00007ffff7f8db82 in ?? () from /usr/lib/libcheck.so.0
#18 0x00007ffff7f8e1a2 in srunner_run_tagged () from /usr/lib/libcheck.so.0
#19 0x00005555555552a8 in main ()

It seems that drop_in_place is called right here:

*boxed_slice_ref = boxed.into();

What does the C side of your code look like? Did you pass in a pointer to an initialized c_slice::Box<u8>? *boxed_slice_ref = boxed.into(); will drop whatever c_slice::Box<u8> was previously stored in *boxed_slice_ref.

Nice observation. That never occurred to me. No, it is not initialized. This is essentially the test case:

START_TEST(some_test)
{
  slice_boxed_uint8_t s;
  test(&s);
}
END_TEST

where slice_boxed_uint8_t is defined as

typedef struct slice_boxed_uint8 {

    uint8_t * ptr;

    size_t len;

} slice_boxed_uint8_t;

What would I even initialize this to? The only thing I can think of is to create some initialization function on the rust side so that rust can then drop it when i call test?

Edit: I added an initialization function in rust and now call this on the C side and it fixes all of my problems. Thanks @bjorn3

#[ffi_export]
pub fn init_box() -> c_slice::Box<u8> {
    c_slice::Box::<u8>::default()
}
START_TEST(some_test)
{
  slice_boxed_uint8_t s = init_box();
  test(&s);
}
END_TEST

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.