Я пытаюсь использовать LD_PRELOAD для перехвата функции PyDict_New. Я проверил, что этот рецепт работал с getpid в интерпретаторе python, и я адаптировал его для использования PyDict_New вместо этого, но он просто не работает, как я ожидаю. Хотя я четко выделяю словари, и эта функция должна использоваться, мое переопределение не вызывается.
Что я делаю не так?
Предпосылки: Я пытаюсь отладить проблему в очень большой системе. Я обнаружил, что есть указатель с плохим подсчетом ссылок. Я знаю, где именно выделяется dict, и где проблема проявляется, но я вполне уверен, что счет идет плохо в какое-то промежуточное время, а простая трассировка кода не будет выполняться, так как dict кэшируется и повторно используется (через PyDict_New) системой gc.
LD_PRELOAD может перегружать только те функции, которые сами загружаются динамически. Если вы используете двоичный код python, PyDict_New не динамически загружается, и поэтому нет возможности для динамического загрузчика перехватить разрешение этого символа. Если вы вместо этого создадите свой собственный "python", скомпилировав свой собственный двоичный файл и связавшись с libpython.so, он должен работать. Вот что вам нужно будет добавить в вашу программу (/tmp/foo.c):
#include "Python.h"
int
main(int argc, char **argv)
{
return Py_Main(argc, argv);
}
И вы можете просто построить его с помощью: gcc -o foo -I/usr/include/python2.7 foo.c -lpython2.7
После этого LD_PRELOAD на. /foo должен работать.
Я думаю, было бы намного проще в вашем случае просто загрузить исходный дистрибутив Python (для соответствующей вам версии), построить его в режиме отладки и запустить приложение с ним.
Этот метод обеспечит вам большую гибкость при отладке проблемы. Например, вы можете установить условные точки останова в PyDict_New
или просто заменить его своей собственной версией.