Почему мне не нужно освобождать эту память? - PullRequest
2 голосов
/ 09 апреля 2011

Я пишу расширение 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 узнает, когда память, на которую указывает «команда», может быть освобождена?Как не происходит утечка памяти?

1 Ответ

6 голосов
/ 09 апреля 2011

Документация говорит об этом для спецификатора формата "s" в PyArg_ParseTuple:

s (строка или Unicode) [const char *]
Преобразуйте строку Python или объект Unicode в указатель C на строку символов.Вы не должны предоставлять хранилище для самой строки;указатель на существующую строку сохраняется в переменной символьного указателя, адрес которой вы передаете.

Это означает, что указатель указывает на память, которой управляет сам Python.

Если выкопайтесь в исходном коде Python (я использую версию 3.2), вы найдете PyArg_ParseTuple в Python/getargs.c.Если вы отслеживаете выполнение (глазного яблока mark-I должно быть достаточно, если вы уже знаете C), вы получите convertsimple, который обрабатывает некоторые строки формата простого типа данных (например, «s»).Затем взгляните на ветвь 's' коммутатора, и вы увидите следующее:

char **p = va_arg(*p_va, char **);
/* ... */
*p = PyBytes_AS_STRING(uarg);

И небольшой щелчок даст определение PyBytes_AS_STRING:

#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \
                                (((PyBytesObject *)(op))->ob_sval))

Таким образом, все, что на самом деле делает, - это передает вам указатель на поле ob_sval внутри объекта Python;Python управляет памятью для своих внутренних объектов.

Итак, вы не должны освобождать вашу строку command, так как она в конечном итоге указывает на некоторые из внутренних данных Python, а сам Python отвечает за эту память.Отсюда и предупреждение «руки прочь» в документации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...