gpt4 book ai didi

python - tp_clear、tp_dealloc 和 tp_free 之间有什么区别?

转载 作者:太空狗 更新时间:2023-10-29 16:12:24 25 4
gpt4 key购买 nike

我有一个用于模糊字符串搜索的自定义 python 模块,实现 Levenshtein 距离计算,它包含一个 python 类型,称为 levtree,它有两个成员,一个指向 wlevtree C 类型(称为树)的指针,它完成所有计算和一个 PyObject * 指向 python 字符串的 python 列表,称为 wordlist。这是我需要的:

-当我创建一个新的 levtree 实例时,我使用一个构造函数,该构造函数将字符串元组作为其唯一输入(并且它是实例将在其中执行所有搜索的字典),该构造函数将必须创建一个wordlist 的新实例到 levtree 的新实例,并将输入元组的内容复制到 wordlist 的新实例。这是我的第一个代码片段和我的第一个问题:

static int
wlevtree_python_init(wlevtree_wlevtree_obj *self, PyObject *args, PyObject *kwds)
{
int numLines; /* how many lines we passed for parsing */
wchar_t** carg; /* argument to pass to the C function*/
unsigned i;

PyObject * strObj; /* one string in the list */
PyObject* intuple;

/* the O! parses for a Python object (listObj) checked
to be of type PyList_Type */
if (!(PyArg_ParseTuple(args, "O!", &PyTuple_Type, &intuple)))
{
return -1;
}

/* get the number of lines passed to us */
numLines = PyTuple_Size(intuple);
carg = malloc(sizeof(char*)*numLines);

/* should raise an error here. */
if (numLines < 0)
{
return -1; /* Not a list */
}

self->wordlist = PyList_New(numLines);
Py_IncRef(self->wordlist);
for(i=0; i<numLines; i++)
{

strObj = PyTuple_GetItem(intuple, i);
//PyList_Append(self->wordlist, string);
PyList_SetItem(self->wordlist, i, strObj);
Py_IncRef(strObj);
}

/* iterate over items of the list, grabbing strings, and parsing
for numbers */
for (i=0; i<numLines; i++)
{

/* grab the string object from the next element of the list */
strObj = PyList_GetItem(self->wordlist, i); /* Can't fail */

/* make it a string */


if(PyUnicode_Check(strObj))
{
carg[i] = PyUnicode_AsUnicode( strObj );
if(PyErr_Occurred())
{
return -1;
}
}
else
{
strObj = PyUnicode_FromEncodedObject(strObj,NULL,NULL);
if(PyErr_Occurred())
{
return -1;
}
carg[i] = PyUnicode_AsUnicode( strObj );
}
}
self->tree = (wlevtree*) malloc(sizeof(wlevtree));
wlevtree_init(self->tree,carg,numLines);
free(carg);
return 0;
}

我是否必须调用 Py_IncRef(self->wordlist);在 self->wordlist = PyList_New(numLines) 之后;或者它是多余的,因为引用已经在 PyList_new 中增加了?然后我对 PyList_SetItem(self->wordlist, i, strObj); 也有同样的疑问和 Py_IncRef(strObj);..

-当我销毁 levtree 的一个实例时,我想调用释放树占用空间的 C 函数,销毁 wordlist 并减少 wordlist 中包含的所有字符串的所有引用计数。这是我的 tp_dealloc:

static void
wlevtree_dealloc(wlevtree_wlevtree_obj* self)
{
//wlevtree_clear(self);
if(self->tree!=NULL)
{
wlevtree_free(self->tree);
}
free(self->tree);
PyObject *tmp, *strObj;
unsigned i;
int size = PyList_Size(self->wordlist);
for(i=0; i<size; i++)
{
strObj = PyList_GetItem(self->wordlist, i);
Py_CLEAR(strObj);
}
Py_CLEAR(self->wordlist);
Py_TYPE(self)->tp_free((PyObject *)self);
}

在这里进行所有的重新分配工作是否正确?目前我没有 tp_clear 和 tp_free,我需要它们吗?我目前的代码适用于分配,但不适用于释放,因为即使我可以多次调用同一个 python 变量上的 init,在每个 python 脚本(工作正常)的末尾,我得到一个“Segmentation Fault”让我觉得在重新分配过程中出现了问题..

最佳答案

tp_clear 仅在您实现 cyclic garbage collection 时才需要.这似乎不是必需的,因为您只维护对 Python unicode 对象的引用。

tp_dealloc 在对象的引用计数降为零时调用。这是您销毁对象及其成员的地方。然后它应该通过调用 tp_free 释放对象占用的内存。

tp_free 是释放对象内存的地方。仅当您自己实现 tp_alloc 时才实现它。

tp_dealloctp_free 分开的原因是,如果你的类型是子类化的,那么只有子类知道内存是如何分配的,以及如何正确释放内存。

如果您的类型是现有类型的子类,您的tp_dealloc 可能需要调用派生类的tp_dealloc,但这取决于具体情况.

总而言之,您似乎正确地处理了对象销毁(除了在错误退出函数时泄漏了 carg)。

关于python - tp_clear、tp_dealloc 和 tp_free 之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24468667/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com