I have a Python program that interfaces with a PyBind11 C++ library.
Somewhere in the library, something is throwing an std::bad_alloc
. Python catches this and handily raises an exception:
MemoryError: std::bad_alloc
Running it all in GDB:
gdb --ex run --args python3 ./my_program
Doesn't result in a break at the point of bad allocation.
If I could get Python to segfault on the bad allocation or tell GDB to catch the exception before Python does, I'd be able to debug this. Unfortunately, I'm not sure how to do either.
Debugging this requires a few steps. First, we're going to need debugging symbols. PyBind11 strips these, so we have to get them back.
My CMake file looked like this:
cmake_minimum_required(VERSION 3.10)
find_package(pybind11 REQUIRED)
pybind11_add_module(my_python_module my_python_module.cpp)
target_compile_features(my_python_module PUBLIC cxx_std_17)
to get symbols back I need it to look like this:
cmake_minimum_required(VERSION 3.10)
find_package(pybind11 REQUIRED)
pybind11_add_module(my_python_module my_python_module.cpp)
target_compile_features(my_python_module PUBLIC cxx_std_17)
target_link_libraries(my_python_module PRIVATE pybind11::module)
add_library(restore_default_visibility INTERFACE)
target_compile_options(restore_default_visibility INTERFACE -fvisibility=default)
target_link_libraries(my_python_module PRIVATE restore_default_visibility)
I also need to get a Debug build:
cmake -DCMAKE_BUILD_TYPE=Debug ..
Now, I can start my Python program:
gdb --args python3 ./my_program
One GDB starts, I set a breakpoint for the std::bad_alloc
:
catch throw std::bad_alloc
Now I can run my program by typing c
.
Later, when it crashes, I can use the bt
command to get a backtrace, up
and down
to navigate the stack, print
show the contents of variables, and Ctrl+X+A
to see the source code.