python-c-api 引用计数

python-c-api reference count

我的 python 代码将一些字典和列表传递给 C,如下所示:

if (!PyArg_ParseTuple(args, "O!lO!O!O!O!O!", &PyList_Type,&list,&los,&PyDict_Type,&entity_len,&PyDict_Type,&inlist_len,&PyList_Type,&inindex,&PyDict_Type,&inlist,&PyList_Type,&tokens))
        return NULL; 

可以得到这样的物品吗?

int i = PyInt_AS_LONG(PyList_GetItem(PyDict_GetItem(inlist,PyList_GetItem(tokens,pi)),current_index[pi]))

我需要在 python 中调用我的 C 函数 10K 次,在我的代码 运行 大约 100 次之后,它显示段错误 11。我该如何修复它?

我不建议这样做,你应该对两者进行错误检查 PyDict_GetItem and PyList_GetItem:

PyObject *obj = PyList_GetItem(args)
if(!obj){
    return NULL
}
// Same for PyDict_GetItem with the difference
// that PyDict won't set an exception, so you 
// probably need to set it yourself.

两个 *_GetItem 功能 return NULL 当出现问题时。因此,如果您只是简单地链接这些调用而没有进行适当的错误检查,那么如果这些 return 之一 NULL.

您将 运行 陷入问题

此外,这两个函数 return a borrowed reference to the Object:

The advantage of borrowing over owning a reference is that you don’t need to take care of disposing of the reference on all possible paths through the code — in other words, with a borrowed reference you don’t run the risk of leaking when a premature exit is taken. The disadvantage of borrowing over owning is that there are some subtle situations where in seemingly correct code a borrowed reference can be used after the owner from which it was borrowed has in fact disposed of it.

(强调我的)

所以您通常不应该担心 Py_DECREF他们。不过要小心;如果您需要使用引用,将其存储或传递到别处,您应该 增加它的引用并获得它的所有权。

最后,我不是 100% 确定将借用引用传递给 PyDict 会产生什么效果;在文档中找不到任何内容。不过,看着 source for PyDict_GetItem,我看不到它 DECREFing key 参数,所以我认为那里不应该有问题。