为什么在没有销毁对象时调用python ctypes类描述符?

时间:2016-05-05 12:59:08

标签: python ctypes

>>> from ctypes import *
>>> class A(Structure):
...  _fields_ = [('a', c_int)]
...  def __del__(self):
...   print("destructor called")
... 
>>> a = (A * 10)()
>>> a[0]
<__main__.A object at 0x7f93038cdd08>
>>> a[0]
destructor called
<__main__.A object at 0x7f93038cde18>
>>> a[0]
destructor called
<__main__.A object at 0x7f93038cdd08>
>>> a[0]
destructor called
<__main__.A object at 0x7f93038cde18>

为什么在这里调用析构函数?为什么每次对象的地址都不同?为什么python不会因双重自由错误而崩溃?

1 个答案:

答案 0 :(得分:3)

a是一个代理对象,表示Python世界中的C结构数组。每次索引此对象时,ctypes都会为您创建A类的新实例,以代理包含的C结构。

现在,因为您不存储对此新对象的任何引用,所以只要它的repr()值已在解释器中回显,它也会被垃圾收集。

您可以将a[0]生成的对象存储在新变量中:

>>> foo = a[0]
>>> foo
<__main__.A object at 0x11061ea60>

此对象将始终与您通过索引a的位置0创建的任何其他对象不同,但它们都表示相同的C结构,因为它们引用相同的地址:

>>> bar = a[0]
>>> foo is bar
False
>>> addressof(foo) == addressof(bar)
True

如果删除此引用,则会再次销毁该对象(假设您当然没有创建对Python代理对象的更多引用):

>>> del foo
destructor called