mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
Bugfix/Check actual value when deregistering pybind11 instance (#2252)
* Add tests demonstrating the problem with deregistering pybind11 instances * Fix deregistering of different pybind11 instance from internals Co-authored-by: Yannick Jadoul <yannick.jadoul@belgacom.net> Co-authored-by: Blistic <wots_wot@hotmail.com>
This commit is contained in:
parent
b9d00273ee
commit
2b6b98e28f
@ -258,7 +258,7 @@ inline bool deregister_instance_impl(void *ptr, instance *self) {
|
|||||||
auto ®istered_instances = get_internals().registered_instances;
|
auto ®istered_instances = get_internals().registered_instances;
|
||||||
auto range = registered_instances.equal_range(ptr);
|
auto range = registered_instances.equal_range(ptr);
|
||||||
for (auto it = range.first; it != range.second; ++it) {
|
for (auto it = range.first; it != range.second; ++it) {
|
||||||
if (Py_TYPE(self) == Py_TYPE(it->second)) {
|
if (self == it->second) {
|
||||||
registered_instances.erase(it);
|
registered_instances.erase(it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -420,6 +420,16 @@ TEST_SUBMODULE(class_, m) {
|
|||||||
py::class_<PyPrintDestructor>(m, "PyPrintDestructor")
|
py::class_<PyPrintDestructor>(m, "PyPrintDestructor")
|
||||||
.def(py::init<>())
|
.def(py::init<>())
|
||||||
.def("throw_something", &PyPrintDestructor::throw_something);
|
.def("throw_something", &PyPrintDestructor::throw_something);
|
||||||
|
|
||||||
|
struct SamePointer {};
|
||||||
|
static SamePointer samePointer;
|
||||||
|
py::class_<SamePointer, std::unique_ptr<SamePointer, py::nodelete>>(m, "SamePointer")
|
||||||
|
.def(py::init([]() { return &samePointer; }))
|
||||||
|
.def("__del__", [](SamePointer&) { py::print("__del__ called"); });
|
||||||
|
|
||||||
|
struct Empty {};
|
||||||
|
py::class_<Empty>(m, "Empty")
|
||||||
|
.def(py::init<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <int N> class BreaksBase { public:
|
template <int N> class BreaksBase { public:
|
||||||
|
@ -368,3 +368,18 @@ def test_non_final_final():
|
|||||||
def test_exception_rvalue_abort():
|
def test_exception_rvalue_abort():
|
||||||
with pytest.raises(RuntimeError):
|
with pytest.raises(RuntimeError):
|
||||||
m.PyPrintDestructor().throw_something()
|
m.PyPrintDestructor().throw_something()
|
||||||
|
|
||||||
|
|
||||||
|
# https://github.com/pybind/pybind11/issues/1568
|
||||||
|
def test_multiple_instances_with_same_pointer(capture):
|
||||||
|
n = 100
|
||||||
|
instances = [m.SamePointer() for _ in range(n)]
|
||||||
|
for i in range(n):
|
||||||
|
# We need to reuse the same allocated memory for with a different type,
|
||||||
|
# to ensure the bug in `deregister_instance_impl` is detected. Otherwise
|
||||||
|
# `Py_TYPE(self) == Py_TYPE(it->second)` will still succeed, even though
|
||||||
|
# the `instance` is already deleted.
|
||||||
|
instances[i] = m.Empty()
|
||||||
|
# No assert: if this does not trigger the error
|
||||||
|
# pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
|
||||||
|
# and just completes without crashing, we're good.
|
||||||
|
Loading…
Reference in New Issue
Block a user