Skip to content

[c++] Invalid free when destroying a class with an std::string member #1842

Open
@Volker-Weissmann

Description

@Volker-Weissmann

Input C/C++ Header

#include <string>
namespace MySpace {
	class MyString {
		std::string internal;
	public:
		MyString();
		~MyString();
	};
	MyString::MyString() {printf("constructing MyString\n");}
	MyString::~MyString(){printf("destructing MyString\n");}
}

Bindgen Invocation

let wl = "MySpace.*";
bindgen::Builder::default()
        .header("wrapper.hpp")
        .parse_callbacks(Box::new(bindgen::CargoCallbacks))
        .clang_arg("-x")
        .clang_arg("c++")
        .opaque_type("std::.*")
        .whitelist_var(wl)
        .whitelist_type(wl)
        .whitelist_function(wl)
        .generate()

Actual Results

pub type std_string = [u64; 4usize];
#[repr(C)]
#[derive(Debug)]
pub struct MySpace_MyString {
    pub internal: std_string,
}
#[test]
fn bindgen_test_layout_MySpace_MyString() {
    assert_eq!(
        ::std::mem::size_of::<MySpace_MyString>(),
        32usize,
        concat!("Size of: ", stringify!(MySpace_MyString))
    );
    assert_eq!(
        ::std::mem::align_of::<MySpace_MyString>(),
        8usize,
        concat!("Alignment of ", stringify!(MySpace_MyString))
    );
    assert_eq!(
        unsafe { &(*(::std::ptr::null::<MySpace_MyString>())).internal as *const _ as usize },
        0usize,
        concat!(
            "Offset of field: ",
            stringify!(MySpace_MyString),
            "::",
            stringify!(internal)
        )
    );
}
extern "C" {
    #[link_name = "\u{1}_ZN7MySpace8MyStringC1Ev"]
    pub fn MySpace_MyString_MyString(this: *mut MySpace_MyString);
}
extern "C" {
    #[link_name = "\u{1}_ZN7MySpace8MyStringD1Ev"]
    pub fn MySpace_MyString_MyString_destructor(this: *mut MySpace_MyString);
}
impl MySpace_MyString {
    #[inline]
    pub unsafe fn new() -> Self {
        let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
        MySpace_MyString_MyString(__bindgen_tmp.as_mut_ptr());
        __bindgen_tmp.assume_init()
    }
    #[inline]
    pub unsafe fn destruct(&mut self) {
        MySpace_MyString_MyString_destructor(self)
    }
}

this looks fine, but if I run

let mut val = MySpace_MyString::new();
val.destruct();

I get the output

constructing MyString
destructing MyString
free(): invalid pointer
Aborted (core dumped)

Expected Results

There should be no invalid free, the code looks fine to me. And it works if I use C++ instead of rust.

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