简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM