我正在编写一个Python C扩展,在列出的here示例中,有一段代码:
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 :(得分:6)
documentation说明PyArg_ParseTuple
的“s”格式说明符:
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);
稍微一点点就会产生PyBytes_AS_STRING
:
#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \
(((PyBytesObject *)(op))->ob_sval))
所以这一切真的就是在Python对象中向你发送指向字段ob_sval
的指针; Python正在管理其内部对象的内存。
所以,你不应该释放你的command
字符串,因为它最终指向Python的一些内部数据,而Python本身负责该内存。因此,文档中的“手动”警告。