Description
Issue description
Having a class which holds the same pointer inside can crash.
The essence of the problem is that register_instance
and deregister_instance
search all instances with the same pointer and then select with matching type: Py_TYPE(self) == Py_TYPE(it->second)
. In certain situations there could be multiple instance of the same type and same pointer.
Reproducible example code
This class can cause a problem:
struct SamePointer {};
static SamePointer samePointer;
py::class_<SamePointer, std::unique_ptr<SamePointer, py::nodelete>>(m, "SamePointer").def(py::init<>([&]() {
return &samePointer;
}));
To reproduce you need regular simple class:
struct Empty {};
py::class_<Empty> (m, "Empty")
.def(py::init<>());
And this python code
import m
x = []
for _ in range(100):
x.append(m.SamePointer())
for j in range(2):
for i in range(100):
if i % 2 == j:
x[i] = m.Empty()
Creating other python classes will reuse the same python object, which was meant to be freed by python, but still considered valid by pybind.
This line will be triggered pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
Maybe it is a bad idea to write a class this way, but it was non obvious and took a lot of time to catch a failure and debug.