gpt4 book ai didi

python - 为指向 ctypes 结构的指针释放内存时出错?

转载 作者:太空宇宙 更新时间:2023-11-04 00:03:43 29 4
gpt4 key购买 nike

我在 Python 中使用 C 扩展模块(称之为 ext),使用 ctypes 访问 C 库。我有两个 ctypes 结构,Foo 和 Bar,它们循环指向彼此。明确地,Bar 持有一个指向 Foo 实例的 ctypes 指针,而 Foo 持有一个 void 指针(出于很长的原因),该指针被分配给 Bar 的一个实例,即

class Foo(Structure):
_fields_ = [("number", c_int),
("ptr", c_void_p)]

class Bar(Structure):
_fields_ = [("ptr", POINTER(Foo))]
def __init__(self, f):
ext.init(byref(f), byref(self))

f = Foo()
b = Bar(f)

分配指针的 ext.init 的 C 代码如下所示:

void init(struct Foo* f, struct Bar* b){
f->ptr = b;
b->ptr = f;
}

我现在可以打印 number

print(b.ptr.contents.number)

但是如果我第二次访问这个变量,我会得到这个错误:

"python(1104,0x7fff75425300) malloc: *** error for object 0x10706b6e0:
pointer being freed was not allocated"

我相信 ctypes 总是在您检索属性时创建一个新对象,所以问题可能是 Bar 无法释放内存 ptr 指向,因为它没有分配它?如果有区别的话,Foo 和 Bar 在不同的 C 扩展中。

更新

我想我现在对事情的理解稍微好一点了。当我打电话时

print(b.ptr.contents.number)

(我认为)为 b.ptr.contents 创建了一个新的 python 对象。然后,当它在 print 语句之后超出范围时, Foo.__del__ 被调用(我至少确定最后一部分,因为我在 Foo.__del__ 中添加了一个 print 语句)。

Foo.__del__ 被设置为调用C 库中的一个函数来释放实例中的所有指针(真正的结构比上面更复杂)。

我不明白对象 b.ptr.contents 是如何创建的。如果它不调用 Foo.__init__,那么指针的内存就不会被分配,所以我得到上面的错误也许是有意义的?

最佳答案

感谢@eryksun 为我解决了这个问题。如果它对其他人有用,问题是我有:

class Foo(Structure):
...
def __del__(self):
ext.free_pointers(byref(self))

其中 free_pointers 是一个 C 函数,它释放了 C 的 Foo 结构实例中的所有指针。正如 eryksun 指出的那样,当我访问 b.ptr.contents 时,这会生成一个 Foo 实例,但它有一个成员 _b_needsfree_ 被设置为 0(这样你的原始实例在 C 中,每当您访问指针时都不会被释放),所以我要做的就是解决这个问题,就是检查这个变量,即,

class Foo(Structure):
...
def __del__(self):
if self._b_needsfree_ == 1:
ext.free_pointers(byref(self))

关于python - 为指向 ctypes 结构的指针释放内存时出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32503701/

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