@@ -459,6 +459,64 @@ you can use ``py::detail::overload_cast_impl`` with an additional set of parenth
459
459
other using the ``.def(py::init<...>()) `` syntax. The existing machinery
460
460
for specifying keyword and default arguments also works.
461
461
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
+
462
520
.. _native_enum :
463
521
464
522
Enumerations and internal types
0 commit comments