>>> 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不会因双重自由错误而崩溃?
答案 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