Есть ли какие-либо ошибки подсчета ссылок / сборки мусора в Python при работе с кодом C? - PullRequest
6 голосов
/ 29 мая 2010

Просто ради этого я решил создать схему привязки к libpython , чтобы вы могли встраивать Python в программы Scheme. Я уже в состоянии обратиться к Python C API, но я действительно не думал об управлении памятью.

Способ работы FFI в mzscheme заключается в том, что я могу вызывать функцию, и если эта функция возвращает указатель на PyObject, то я могу автоматически увеличить счетчик ссылок. Затем я могу зарегистрировать финализатор, который будет уменьшать счетчик ссылок, когда объект Scheme будет собирать мусор. Я просмотрел документацию для подсчета ссылок и не вижу проблем с этим на первый взгляд (хотя в некоторых случаях она может быть неоптимальной). Есть ли какие-то ошибки, которые мне не хватает?

Кроме того, у меня проблемы с изготовлением головок или хвостов документации по циклическому сборщику мусора . Какие вещи мне нужно здесь иметь в виду? В частности, как я могу сообщить Python, что у меня есть ссылка на что-то, чтобы она не собирала это, пока я все еще использую это?

Ответы [ 2 ]

7 голосов
/ 29 мая 2010

Ваша ссылка на http://docs.python.org/extending/extending.html#reference-counts - правильное место. В разделах документации, посвященных расширению и встраиванию и Python / C API, объясняется, как использовать C API.

Подсчет ссылок - одна из раздражающих частей использования C API. Основная проблема заключается в том, чтобы все было прямо: в зависимости от функции API, которую вы вызываете, вы можете иметь или не иметь ссылку на объект, который вы получаете. Будьте осторожны, чтобы понять, принадлежите ли вы ему (и, таким образом, не можете забыть его УДЕРЖИВАТЬ или отдать тому, что украдет его) или заимствуете его (и должны УВЕЛИЧИТЬ его, чтобы сохранить и, возможно, использовать во время выполнения своих функций). Наиболее распространенными ошибками, связанными с этим, являются: 1) неправильное запоминание того, принадлежит ли вам ссылка, возвращаемая определенной функцией, и 2) уверенность, что вы можете заимствовать ссылку на более длительный срок, чем вы.

Вам не нужно делать ничего особенного для циклического сборщика мусора. Это просто для исправления недостатка в подсчете ссылок и не требует прямого доступа.

3 голосов
/ 29 мая 2010

Самая большая ошибка, которую я знаю, с подсчетом ссылок и C API - это вещь __del__. Когда у вас есть заимствованная ссылка на что-то, вы думаете, что можете обойтись без INCREF, потому что вы не отказываетесь от GIL, пока используете эту ссылку. Но если вы в конечном итоге удалите объект (например, удалив его из списка), вполне возможно, что вы вызовете вызов __del__, который может удалить ссылку, которую вы заимствовали из-под ваших ног. Очень сложно.

Если вы УВЕЛИЧИВАЕТЕ (а затем, конечно, ОТМЕНАЕТЕ) все заимствованные ссылки, как только вы их получите, проблем не должно быть.

...