Skip to content

Pybind incorrectly deregisters instances (by type comparison), yields errors when C++ recycles memory #1238

Open
@EricCousineau-TRI

Description

@EricCousineau-TRI

I ran into an interesting (read: Heisen) bug that occurred when I had code that looked like this:

obj = m.UniquePtrHeld(1)
m.unique_ptr_terminal(obj)  # Destroys the value held by `obj`
obj = m.UniquePtrHeld(1)

After C++ destroyed the first instance, the second instance was allocated into the same address, when casting the instance back, pybind registered a new instance (in get_internals().registered_instances) when the same ptr-value, but a different instance.
In deregister_instance_impl, it finds all values that match the given ptr, and only checks if the Py_TYPE is the same.

The fix in this case is just to compare instances (if there wasn't a strong reason for getting the type). An example change:
https://github.com/EricCousineau-TRI/pybind11/blob/feature/unique_ptr_arg_pr1-wip/include/pybind11/detail/class.h#L225

Even though I encountered this for my unique_ptr PRs, I believe it could still be an issue when returning bare pointers, say:

// c++
struct MyType { int value; }
...
m.def("do_something", [](MyType *in) {
  delete in;
  return new MyType{10};
});

# python
obj = m.MyType(10)
obj = do_something(obj);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions