Skip to content

Commit 31886ec

Browse files
committed
Expand comment in smart_holder::from_unique_ptr()
1 parent 4c95a2a commit 31886ec

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

include/pybind11/detail/struct_smart_holder.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,21 @@ struct smart_holder {
354354
// Relinquish ownership only after successful construction of owner
355355
(void) unq_ptr.release();
356356

357-
// Publish either the subobject alias (for identity/VI) or the full object.
357+
// Publish either the MI/VI subobject pointer (if provided) or the full object.
358+
// Why this is needed:
359+
// * The `owner` shared_ptr must always manage the true object start (T*).
360+
// That ensures the deleter is invoked on a valid object header, so the
361+
// virtual destructor can dispatch safely (critical on MSVC with virtual
362+
// inheritance, where base subobjects are not at offset 0).
363+
// * However, pybind11 needs to *register* and expose the subobject pointer
364+
// appropriate for the type being bound.
365+
// This pointer may differ from the T* object start under multiple/virtual
366+
// inheritance.
367+
// This is achieved by using an aliasing shared_ptr<void>:
368+
// - `owner` retains lifetime of the actual T* object start for deletion.
369+
// - `vptr` points at the adjusted subobject (mi_subobject_ptr), giving
370+
// Python the correct identity/registration address.
371+
// If no subobject pointer is passed, we simply publish the full object.
358372
if (mi_subobject_ptr) {
359373
hld.vptr = std::shared_ptr<void>(owner, mi_subobject_ptr);
360374
} else {

0 commit comments

Comments
 (0)