Skip to content

Commit bd560ac

Browse files
committed
smart pointer refcount fix by @dean0x7d with slight modifications (fixes #471)
1 parent 0a9ef9c commit bd560ac

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

include/pybind11/pybind11.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,7 @@ class class_ : public detail::generic_type {
11341134
} catch (const std::bad_weak_ptr &) {
11351135
new (&inst->holder) holder_type(inst->value);
11361136
}
1137+
inst->owned = true;
11371138
}
11381139

11391140
/// Initialize holder object, variant 2: try to construct from existing holder object, if possible
@@ -1144,6 +1145,7 @@ class class_ : public detail::generic_type {
11441145
new (&inst->holder) holder_type(*holder_ptr);
11451146
else
11461147
new (&inst->holder) holder_type(inst->value);
1148+
inst->owned = true;
11471149
}
11481150

11491151
/// Initialize holder object, variant 3: holder is not copy constructible (e.g. unique_ptr), always initialize from raw pointer

tests/test_issues.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,28 @@ void init_issues(py::module &m) {
290290
for (auto &e : nothrows) l.append(py::cast(e));
291291
return l;
292292
});
293-
}
293+
294+
/// Issue #471: shared pointer instance not dellocated
295+
class SharedChild : public std::enable_shared_from_this<SharedChild> {
296+
public:
297+
SharedChild() { print_created(this); }
298+
~SharedChild() { print_destroyed(this); }
299+
};
300+
301+
class SharedParent {
302+
public:
303+
SharedParent() : child(std::make_shared<SharedChild>()) { }
304+
const SharedChild &get_child() const { return *child; }
305+
306+
private:
307+
std::shared_ptr<SharedChild> child;
308+
};
309+
310+
py::class_<SharedChild, std::shared_ptr<SharedChild>>(m, "SharedChild");
311+
py::class_<SharedParent, std::shared_ptr<SharedParent>>(m, "SharedParent")
312+
.def(py::init<>())
313+
.def("get_child", &SharedParent::get_child, py::return_value_policy::reference);
314+
};
294315

295316

296317
// MSVC workaround: trying to use a lambda here crashes MSCV

tests/test_issues.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import pytest
22
import gc
3+
from pybind11_tests import ConstructorStats
34

45

56
def test_regressions():
@@ -187,3 +188,16 @@ def test_dupe_assignment():
187188
""" Issue 461: overwriting a class with a function """
188189
from pybind11_tests.issues import dupe_exception_failures
189190
assert dupe_exception_failures() == []
191+
192+
193+
def test_enable_shared_from_this_with_reference_rvp():
194+
""" Issue #471: shared pointer instance not dellocated """
195+
from pybind11_tests import SharedParent, SharedChild
196+
197+
parent = SharedParent()
198+
child = parent.get_child()
199+
200+
cstats = ConstructorStats.get(SharedChild)
201+
assert cstats.alive() == 1
202+
del child, parent
203+
assert cstats.alive() == 0

0 commit comments

Comments
 (0)