From bd560acf401596136b98a4540c2454ad07a99e9e Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Thu, 3 Nov 2016 11:53:35 +0100 Subject: [PATCH] smart pointer refcount fix by @dean0x7d with slight modifications (fixes #471) --- include/pybind11/pybind11.h | 2 ++ tests/test_issues.cpp | 23 ++++++++++++++++++++++- tests/test_issues.py | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 10c0e7a28..f89fae865 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1134,6 +1134,7 @@ private: } catch (const std::bad_weak_ptr &) { new (&inst->holder) holder_type(inst->value); } + inst->owned = true; } /// Initialize holder object, variant 2: try to construct from existing holder object, if possible @@ -1144,6 +1145,7 @@ private: new (&inst->holder) holder_type(*holder_ptr); else new (&inst->holder) holder_type(inst->value); + inst->owned = true; } /// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer diff --git a/tests/test_issues.cpp b/tests/test_issues.cpp index f5467cb14..362ad448b 100644 --- a/tests/test_issues.cpp +++ b/tests/test_issues.cpp @@ -290,7 +290,28 @@ void init_issues(py::module &m) { for (auto &e : nothrows) l.append(py::cast(e)); return l; }); -} + + /// Issue #471: shared pointer instance not dellocated + class SharedChild : public std::enable_shared_from_this { + public: + SharedChild() { print_created(this); } + ~SharedChild() { print_destroyed(this); } + }; + + class SharedParent { + public: + SharedParent() : child(std::make_shared()) { } + const SharedChild &get_child() const { return *child; } + + private: + std::shared_ptr child; + }; + + py::class_>(m, "SharedChild"); + py::class_>(m, "SharedParent") + .def(py::init<>()) + .def("get_child", &SharedParent::get_child, py::return_value_policy::reference); +}; // MSVC workaround: trying to use a lambda here crashes MSCV diff --git a/tests/test_issues.py b/tests/test_issues.py index cf645ef9f..208cf3b41 100644 --- a/tests/test_issues.py +++ b/tests/test_issues.py @@ -1,5 +1,6 @@ import pytest import gc +from pybind11_tests import ConstructorStats def test_regressions(): @@ -187,3 +188,16 @@ def test_dupe_assignment(): """ Issue 461: overwriting a class with a function """ from pybind11_tests.issues import dupe_exception_failures assert dupe_exception_failures() == [] + + +def test_enable_shared_from_this_with_reference_rvp(): + """ Issue #471: shared pointer instance not dellocated """ + from pybind11_tests import SharedParent, SharedChild + + parent = SharedParent() + child = parent.get_child() + + cstats = ConstructorStats.get(SharedChild) + assert cstats.alive() == 1 + del child, parent + assert cstats.alive() == 0