Я пишу расширение Python C, а в приведенных ниже примерах здесь, есть фрагмент кода:
static PyObject * spam_system(PyObject *self, PyObject *args) {
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command)) return NULL;
sts = system(command);
return Py_BuildValue("i", sts);
}
В соответствии с документацией для синтаксического анализа строки с PyArg_ParseTuple "Вы не должны предоставлять хранилище для самой строки, указатель на существующую строку хранится в переменной указателя символа, адрес которой вы передаете". Итак, как Python знает, когда память, на которую указывает "команда", может быть освобождена? Как происходит утечка памяти?
Документация говорит об этом спецификаторе формата s для PyArg_ParseTuple
:
s
(строка или Unicode) [const char *]
Преобразуйте строку Python или объект Unicode в C-указатель на строку символов. Вы не должны предоставлять хранилище для самой строки; указатель на существующую строку сохраняется в переменной указателя символа, адрес которой вы передаете.
Это означает, что указатель указывает на память, которой управляет сам Python.
Если вы вникнете в источник Python (я использую версию 3.2), вы найдете PyArg_ParseTuple
в Python/getargs.c
. Если вы отслеживаете выполнение (глазное яблоко маркировки должно быть достаточным, если вы уже знаете C), вы попадете в convertsimple
, который обрабатывает некоторые простые строки формата данных типа (например, "s" ). Затем просмотрите ветвь 's'
коммутатора, и вы увидите следующее:
char **p = va_arg(*p_va, char **);
/* ... */
*p = PyBytes_AS_STRING(uarg);
И немного grepping даст определение PyBytes_AS_STRING
:
#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \
(((PyBytesObject *)(op))->ob_sval))
Итак, все это действительно означает, что вы передаете указатель на поле ob_sval
внутри объекта Python; Python управляет памятью для своих внутренних объектов.
Итак, вы не должны освобождать строку command
, потому что она заканчивается тем, что указывает на некоторые внутренние данные Python, и сам Python несет ответственность за эту память. Следовательно, предупреждение "руки выключено" в документации.
PyBytes_AS_STRING
, я в основном PyBytes_AS_STRING
свое предположение. Рад быть полезным в любом случае.