smart pointer refcount fix by @dean0x7d with slight modifications (fixes #471)

This commit is contained in:
Wenzel Jakob 2016-11-03 11:53:35 +01:00
parent 0a9ef9c300
commit bd560acf40
3 changed files with 38 additions and 1 deletions

View File

@ -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

View File

@ -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<SharedChild> {
public:
SharedChild() { print_created(this); }
~SharedChild() { print_destroyed(this); }
};
class SharedParent {
public:
SharedParent() : child(std::make_shared<SharedChild>()) { }
const SharedChild &get_child() const { return *child; }
private:
std::shared_ptr<SharedChild> child;
};
py::class_<SharedChild, std::shared_ptr<SharedChild>>(m, "SharedChild");
py::class_<SharedParent, std::shared_ptr<SharedParent>>(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

View File

@ -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