@@ -459,6 +459,64 @@ you can use ``py::detail::overload_cast_impl`` with an additional set of parenth
459459 other using the ``.def(py::init<...>()) `` syntax. The existing machinery
460460 for specifying keyword and default arguments also works.
461461
462+ ☝️ Pitfalls with raw pointers and shared ownership
463+ ==================================================
464+
465+ ``py::class_ ``-wrapped objects automatically manage the lifetime of the
466+ wrapped C++ object, in collaboration with the chosen holder type (see
467+ :ref: `py_class_holder `). When wrapping C++ functions involving raw pointers,
468+ care needs to be taken to not accidentally undermine automatic lifetime
469+ management. For example, ownership is inadvertently transferred here:
470+
471+ .. code-block :: cpp
472+
473+ class Child { };
474+
475+ class Parent {
476+ public:
477+ Parent() : child(std::make_shared<Child>()) { }
478+ Child *get_child() { return child.get(); } /* DANGER */
479+ private:
480+ std::shared_ptr<Child> child;
481+ };
482+
483+ PYBIND11_MODULE(example, m) {
484+ py::class_<Child, std::shared_ptr<Child>>(m, "Child");
485+
486+ py::class_<Parent, std::shared_ptr<Parent>>(m, "Parent")
487+ .def(py::init<>())
488+ .def("get_child", &Parent::get_child); /* PROBLEM */
489+ }
490+
491+ The following Python code leads to undefined behavior, likely resulting in
492+ a segmentation fault.
493+
494+ .. code-block :: python
495+
496+ from example import Parent
497+
498+ print (Parent().get_child())
499+
500+ Part of the ``/* PROBLEM */ `` here is that pybind11 falls back to using
501+ ``return_value_policy::take_ownership `` as the default (see
502+ :ref: `return_value_policies `). The fact that the ``Child `` instance is
503+ already managed by ``std::shared_ptr<Child> `` is lost. Therefore pybind11
504+ will create a second independent ``std::shared_ptr<Child> `` that also
505+ claims ownership of the pointer, eventually leading to heap-use-after-free
506+ or double-free errors.
507+
508+ There are various ways to resolve this issue, either by changing
509+ the ``Child `` or ``Parent `` C++ implementations (e.g. using
510+ ``std::enable_shared_from_this<Child> `` as a base class for
511+ ``Child ``, or adding a member function to ``Parent `` that returns
512+ ``std::shared_ptr<Child> ``), or if that is not feasible, by using
513+ ``return_value_policy::reference_internal ``. What is the best approach
514+ depends on the exact situation.
515+
516+ A highly effective way to stay in the clear — even in pure C++, but
517+ especially when binding C++ code to Python — is to consistently prefer
518+ ``std::shared_ptr `` or ``std::unique_ptr `` over passing raw pointers.
519+
462520.. _native_enum :
463521
464522Enumerations and internal types
0 commit comments