[英]Error releasing memory for a pointer to a ctypes structure?
I am using a C extension module in Python (call it ext) using ctypes to access a C library. 我正在使用ctypes在Python(称为ext)中使用C扩展模块来访问C库。 I have two ctypes structures, Foo and Bar, which circularly point to one another.
我有两个ctype结构,即Foo和Bar,它们互相指向。 Explicitly, Bar holds a ctypes pointer to an instance of Foo, and Foo holds a void pointer (for long reasons) that gets assigned to an instance of Bar, ie
明确地,Bar拥有指向Foo实例的ctypes指针,而Foo拥有(由于长期原因)被分配给Bar实例的void指针,即
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)
where the C code for ext.init
, which assigns the pointers, looks like this: ext.init
的C代码(分配指针)如下所示:
void init(struct Foo* f, struct Bar* b){
f->ptr = b;
b->ptr = f;
}
I can now print number
with 我现在可以打印
number
与
print(b.ptr.contents.number)
But if I access this variable a second time, I get this error: 但是,如果我第二次访问此变量,则会收到此错误:
"python(1104,0x7fff75425300) malloc: *** error for object 0x10706b6e0:
pointer being freed was not allocated"
I believe ctypes always makes a new object whenever you retrieve an attribute, so maybe the problem is that Bar can't release the memory ptr points to since it didn't allocate it? 我相信ctypes总是会在您检索属性时创建一个新对象,所以也许问题在于Bar不能释放内存ptr点,因为它没有分配它? If it makes a difference, Foo and Bar are in different C extensions.
如果有所不同,则Foo和Bar使用不同的C扩展名。
UPDATE UPDATE
I think I understand things slightly better now. 我想我现在对事情的了解要好一些。 When I call
当我打电话
print(b.ptr.contents.number)
(I think) a new python object is created for b.ptr.contents. (我认为)为b.ptr.contents创建了一个新的python对象。 Then, when it goes out of scope after the print statement,
Foo.__del__
gets called (I'm at least sure of the last part, since I added a print statement in Foo.__del__
). 然后,当它在print语句之后超出范围时,
Foo.__del__
被调用(由于我在Foo.__del__
添加了一条print语句,所以我至少可以确定最后一部分)。
Foo.__del__
is set up to call a function in the C library to free all the pointers in the instance (the real struct is more complicated than above). Foo.__del__
设置为调用C库中的一个函数以释放实例中的所有指针(实际结构比上面更复杂)。
I don't understand how the object b.ptr.contents
gets created. 我不明白如何创建对象
b.ptr.contents
。 If it doesn't call Foo.__init__
, then the memory for the pointers wouldn't get allocated, so maybe it would make sense that I get the error above? 如果它没有调用
Foo.__init__
,那么将不会分配指针的内存,所以我得到上面的错误也许是有意义的?
Thanks @eryksun for solving this for me. 感谢@eryksun为我解决了这个问题。 In case it's useful to others, the problem was that I had:
万一它对其他人有用,问题是我有:
class Foo(Structure):
...
def __del__(self):
ext.free_pointers(byref(self))
where free_pointers
was a C function that freed all the pointers in C's Foo struct instance. 其中
free_pointers
是C函数,它释放C的Foo struct实例中的所有指针。 As eryksun points out, when I access b.ptr.contents
, this makes a Foo instance, but it has a member _b_needsfree_
that's set to 0 (so that your original instance in C doesn't get deallocated whenever you access the pointer), so all I had to do to fix the problem, is check this variable, ie, 正如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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.