Skip to content

Incomplete/zero-sized arrays don't affect struct alignment. #684

Closed
@cholcombe973

Description

@cholcombe973

I'm new to the build.rs bindings generation. Last time I generated bindings I used the old method of having it print to stdout and then manually fixing the errors. I'm seeing an alignment error that that I don't know how to solve just yet:


Input C/C++ Header

struct dm_deps {
        uint32_t count;
        uint32_t filler;
        uint64_t device[0];
};

Bindgen Invokation

    let bindings = bindgen::Builder::default()
        .no_unstable_rust()
        .header("wrapper.h")
        .generate()
        .expect("Unable to generate bindings");

Actual Results

---- bindgen_test_layout_dm_deps stdout ----
	thread 'bindgen_test_layout_dm_deps' panicked at 'assertion failed: `(left == right)` (left: `4`, right: `8`): Alignment of dm_deps', /mnt/sdb/repos/lvm-sys/target/debug/build/lvm-sys-7e5868edf14c1ccb/out/bindings.rs:3319
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at /checkout/src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at /checkout/src/libstd/sys_common/backtrace.rs:60
             at /checkout/src/libstd/panicking.rs:355
   3: std::panicking::default_hook
             at /checkout/src/libstd/panicking.rs:365
   4: std::panicking::rust_panic_with_hook
             at /checkout/src/libstd/panicking.rs:549
   5: std::panicking::begin_panic
             at /checkout/src/libstd/panicking.rs:511
   6: std::panicking::begin_panic_fmt
             at /checkout/src/libstd/panicking.rs:495
   7: lvm_sys::bindgen_test_layout_dm_deps
             at ./target/debug/build/lvm-sys-7e5868edf14c1ccb/out/bindings.rs:3319
   8: <F as test::FnBox<T>>::call_box
             at /checkout/src/libtest/lib.rs:1368
             at /checkout/src/libtest/lib.rs:140
   9: std::panicking::try::do_call
             at /checkout/src/libtest/lib.rs:1314
             at /checkout/src/libstd/panic.rs:296
             at /checkout/src/libstd/panicking.rs:454
  10: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:98
  11: std::panicking::try::do_call
             at /checkout/src/libstd/panicking.rs:433
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libtest/lib.rs:1313
             at /checkout/src/libstd/panic.rs:296
             at /checkout/src/libstd/panicking.rs:454
  12: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:98
  13: <F as alloc::boxed::FnBox<A>>::call_box
             at /checkout/src/libstd/panicking.rs:433
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libstd/thread/mod.rs:360
             at /checkout/src/liballoc/boxed.rs:640
  14: std::sys::imp::thread::Thread::new::thread_start
             at /checkout/src/liballoc/boxed.rs:650
             at /checkout/src/libstd/sys_common/thread.rs:21
             at /checkout/src/libstd/sys/unix/thread.rs:84
  15: start_thread
  16: clone

Expected Results

RUST_LOG=bindgen Output

I don't have any additional details from RUST_LOG=bindgen Here's the generated rust binding code:
#[repr(C)]
#[derive(Default)]
pub struct __IncompleteArrayField<T>(::std::marker::PhantomData<T>);
impl <T> __IncompleteArrayField<T> {
    #[inline]
    pub fn new() -> Self {
        __IncompleteArrayField(::std::marker::PhantomData)
    }
    #[inline]
    pub unsafe fn as_ptr(&self) -> *const T { ::std::mem::transmute(self) }
    #[inline]
    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
        ::std::mem::transmute(self)
    }
    #[inline]
    pub unsafe fn as_slice(&self, len: usize) -> &[T] {
        ::std::slice::from_raw_parts(self.as_ptr(), len)
    }
    #[inline]
    pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
        ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
    }
}
impl <T> ::std::fmt::Debug for __IncompleteArrayField<T> {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        fmt.write_str("__IncompleteArrayField")
    }
}
impl <T> ::std::clone::Clone for __IncompleteArrayField<T> {
    #[inline]
    fn clone(&self) -> Self { Self::new() }
}
impl <T> ::std::marker::Copy for __IncompleteArrayField<T> { }
#[repr(C)]
#[derive(Debug, Copy)]
pub struct dm_deps {
    pub count: u32,
    pub filler: u32,
    pub device: __IncompleteArrayField<u64>,
}
#[test]
fn bindgen_test_layout_dm_deps() {
    assert_eq!(::std::mem::size_of::<dm_deps>() , 8usize , concat ! (
               "Size of: " , stringify ! ( dm_deps ) ));
    assert_eq! (::std::mem::align_of::<dm_deps>() , 8usize , concat ! (
                "Alignment of " , stringify ! ( dm_deps ) ));
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions