Skip to content

[QUESTION] : segfault error due to pybind11 object and C++ pointer ownership conflict #2452

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Karim-KT opened this issue Sep 1, 2020 · 3 comments

Comments

@Karim-KT
Copy link

Karim-KT commented Sep 1, 2020

After interfacing with a c++ PQTree library: https://github.com/Gregable/pq-trees
and after calling methods from the PQTree library in python i always get C++ segfaults after the Python interpreter shuts down

This is mostly 'double free or corruption (out)' but also general segfaults.
we noticed that everything in our python function is executed, but after the call to the function, the errors appear (probably because the C++ destructors are called and the error occurs there).

The initial intuition is that:

somewhere, both a pybind11 object and C++ think they own a pointer, and the garbage collector is deleting the pybind object PQNode that has probably already been deleted by C++.

is there any way to prevent occurring segfaults (suppress the pyobject deletion by the garbage collector if it was already freed in c++ by the destructor)?

here is a pastebin to gdb: https://pastebin.com/ifNF6TfW

@YannickJadoul
Copy link
Collaborator

@bstaletic and I have been debugging with you on Gitter. The preliminary conclusion was that (most likely) pybind11 is taking ownership of one of your pointers and that it is deleting them after C++.

I asked you to add print functionality to your destructor to further debug, and you never did that or told us what you got.

Handle this like any other case in C++ where two things delete the same thing: figure out which part of the program shóuld own the code, and make sure the other one doesn't delete it. Also read about pybind11's return_value_policy, if you want pybind11 to not take ownership of a returned pointer.

@Karim-KT
Copy link
Author

Karim-KT commented Sep 2, 2020

The issue is resolved,
it was a memory management issue (an overlap between the python gc and the cpp destructor) which lead to freeing the same pyobject twice

in order to solve it we have resolved to the following

in case of class with init use py::nodelete to make sure Python never deletes any objects of that exact type in question

in case of a module::def() it is advised to use return_value_policy::copy

for further details check:
https://pybind11.readthedocs.io/en/stable/advanced/functions.html
#609 (comment)

@Karim-KT Karim-KT closed this as completed Sep 2, 2020
@YannickJadoul
Copy link
Collaborator

Great! Thanks for letting us know what you did to resolve it and closing the issue! :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants