如何在python中创建悬空指针(在堆栈或堆中)

时间:2012-09-29 14:02:08

标签: python pointers python-3.x stack heap

我想知道有没有办法在python中创建悬空指针?我想我们必须手动删除一个对象,然后该对象的引用将指向一个对程序没有意义的位置。 我找到了这个例子Here

import weakref
class Object:
    pass

o = Object()    #new instance
print ("o id is:",id(o))
r = weakref.ref(o)
print ("r id is:",id(r))
o2 = r()
print ("o2 id is:",id(o2))
print ("r() id is:",id(r()))
print (o is o2)         

del o,o2
print (r(),r)   #If the referent no longer exists, calling the reference object returns None

o = r()         # r is a weak reference object
if o is None:
    # referent has been garbage collected
    print ("Object has been deallocated; can't frobnicate.")
else:
    print ("Object is still live!")
    o.do_something_useful()

在这个例子中哪一个是悬空指针/参考?是o还是r?我很迷惑。 是否也可以在堆栈中创建悬空指针?如果你愿意,给我一些简单的例子,这样我就可以理解它是怎么回事。 提前谢谢。

3 个答案:

答案 0 :(得分:2)

除非Python或扩展中存在错误,否则无法引用解除分配的对象。弱引用指的是对象,只要它是活着的,而不是有助于保持它的存活。在释放对象的那一刻,弱引用的计算结果为None,因此您永远不会得到悬空对象。 (即使弱引用的回调在对象已被解除分配后被称为,而弱引用也取消引用为无,因此你也无法复活它。)

如果你可以引用一个真正的解除分配的对象,Python很可能在第一次访问时崩溃,因为该对象先前持有的内存将被重用,而对象的类型和其他插槽将包含垃圾。永远不会在堆栈上分配Python对象。

如果您有一个用例,为什么需要使用悬空物体,您应该以问题的形式提交用例。

答案 1 :(得分:2)

所有Python对象都存在于堆上。堆栈仅用于函数调用。

如果对象仍然存在,则调用weakref对象会取消引用它并为您提供对该对象的强引用。否则,您获得None。在后一种情况下,您可以将weakref称为“悬空”(在您的示例中为r)。

然而,Python没有任何关于“悬挂指针”的概念,就像C一样。这是不可能的(除了Python中的错误,错误的扩展模块或滥用像ctypes这样的模块)来创建一个引用已删除对象的名称(强引用),因为根据定义,强引用可以保持它们的引用活着。另一方面,弱引用并不是真正悬空的指针,因为如果它们的引用被删除,它们会自动解析为None

请注意,如果滥用ctypes,则可以创建“真正的”悬空指针:

import ctypes
a = (1, 2, 3)
ctypes.pythonapi.Py_DecRef(ctypes.py_object(a))
print a

当您print a现在未定义时会发生什么。它可能会使解释器崩溃,打印(1, 2, 3),打印其他元组或执行随机函数。当然,这只是因为你滥用ctypes;这不是你曾经做的事情。

答案 2 :(得分:1)

如果创建弱引用,则在删除引用的对象时(当引用计数达到零时,或者是未被其他任何引用的对象的闭合循环的一部分时),它将变为“悬空”。这是可能的,因为weakref不会增加引用计数本身(这是弱引用的整点)。

当发生这种情况时,每次尝试“取消引用”weakref对象(调用它)时,它都会返回None

重要的是要记住,在Python中,变量实际上是名称,指向对象。它们实际上是“强引用”。例如:

import weakref

class A:
    pass

# a new object is created, and the name "x" is set to reference the object,
# giving a reference count of 1
x = A() 

# a weak reference is created referencing the object that the name x references
# the reference count is still 1 though, because x is still the only strong
# reference
weak_reference = weakref.ref(x)

# the only strong reference to the object is deleted (x), reducing the reference
# count to 0 this means that the object is destroyed, and at this point
# "weak_reference" becomes dangling, and calls return None
del x

assert weak_reference() is None