Почему мне не нужно освобождать эту память?

1

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

  • 0
    Где написано, что Python освобождает саму память? Я предполагаю, что вам нужно освободить его, когда вы закончите.
  • 2
    Когда он говорит «указатель на существующую строку», я предполагаю, что PyArq_ParseTuple не выделяет память. Хотя это небезопасное предположение, я бы проверил документацию.
Показать ещё 3 комментария
Теги:
memory-leaks

1 ответ

5
Лучший ответ

Документация говорит об этом спецификаторе формата 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 несет ответственность за эту память. Следовательно, предупреждение "руки выключено" в документации.

  • 0
    Спасибо @mu, я должен был подумать, чтобы покопаться в источнике, чтобы выяснить это
  • 0
    @Andrew: я подозревал, что все сводится к PyBytes_AS_STRING , я в основном PyBytes_AS_STRING свое предположение. Рад быть полезным в любом случае.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню