Description
Bug
I am using a large C++ library which makes heavy use of virtual functions and virtual destructor. I am using bindgen's vtable generation which miss virtual destructors on Linux x86_64.
I made a simple repository that exhibit this bug : https://github.com/DevilishSpirits/rust-bindgen-vtable-april25, clone and cargo run
it. fn3()
should be printed if bindgen correctly generated the vtable.
The src/main.cpp
file define a class with pure virtual functions fn1()
, fn2()
and fn3()
, then this class is derived with implementations that echo fnx()
on screen. The level of indirection in the C++ is because I reproduced the style of the library I am using.
Both src/main.cpp
and src/main.rs
contain an example that create the object then call fn3()
and destroy the object. While the C++ code echo fn3()
, the Rust code echo fn1()
. I inspected the vtables using gdb which show that there are 2 virtual destructor prepended in the vtable :
(gdb) info vtbl this
vtable for 'BugIllustrationImpl' @ 0x5555555a8eb0 (subobject @ 0x5555555bfa20):
[0]: 0x55555555b890 <BugIllustrationImpl::~BugIllustrationImpl()>
[1]: 0x55555555b8be <BugIllustrationImpl::~BugIllustrationImpl()>
[2]: 0x55555555b8ea <BugIllustrationImpl::fn1()>
[3]: 0x55555555b908 <BugIllustrationImpl::fn2()>
Rust does not include these virtual destructors and is off by 2 pointers and hence call fn1()
instead of fn3()
:
(gdb) p *bug_vtable
$1 = aa::BugIllustration__bindgen_vtable {
BugIllustration_fn1: 0x55555555b890 <BugIllustrationImpl::~BugIllustrationImpl()>,
BugIllustration_fn2: 0x55555555b8be <BugIllustrationImpl::~BugIllustrationImpl()>,
BugIllustration_fn3: 0x55555555b8ea <BugIllustrationImpl::fn1()>
}
Expected behavior
I expect bindgen to include pointers to the virtual destructor in the vtable or an opaque padding to allow read-only usage of the vtable.
Expected behavior 2
If that is too difficult to implement, at least bindgen should detect that virtual destructor are in use and generate a fake vtable such as the one below :
/// Virtual destructors detected: vtable not generated
#[repr(C, align(8))] // ← shouldn't bindgen explicitely align the struct???
pub struct BugIllustration__bindgen_vtable {
/// Virtual destructors detected: vtable not generated
///
/// Bindgen currently does not support vtable generation of C++ class with
/// virtual destructors. See https://example.com/some/bug/or/link
pub __virtual_destructors_detected: std::convert::Infallible,
}
This clearly tell the user that bindgen attempted to generate the vtable but that it ran into a limitation.
The user can also use the vtable reference and pass it around for it own needs.
Then if bindgen get support for these vtable, existing code is unlikely to break.