4

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

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?我很困惑。是否也可以在堆栈中创建悬空指针?如果你愿意,给我一些简单的例子,这样我就可以理解它是怎么回事。提前致谢。

4

3 回答 3

4

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

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

然而,Python 没有任何与 C 相同的“悬空指针”的概念。ctypes创建一个引用已删除对象的名称(强引用)是不可能的(除非 Python 中的错误、错误的扩展模块或滥用类似 的模块),因为根据定义,强引用使它们的引用保持活动状态。另一方面,弱引用并不是真正的悬空指针,因为None如果它们的引用被删除,它们会自动解析为。

请注意,ctypes滥用可能会创建一个“真正的”悬空指针:

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

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

于 2012-09-29T20:41:06.963 回答
2

除非 Python 中的错误或扩展,否则无法引用已释放的对象。只要对象还活着,弱引用就会引用该对象,而不有助于保持它活着。在对象被释放的那一刻,弱引用评估为无,所以你永远不会得到悬空对象。(即使是在对象已经被释放并且弱引用取消引用到 None之后调用弱引用的回调,所以你也不能复活它。)

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

如果您有一个用例为什么需要使用悬空对象,您应该以问题的形式呈现该用例。

于 2012-09-29T14:16:48.417 回答
1

如果你创建一个弱引用,当被引用的对象被删除时(当它的引用计数达到零,或者是没有被其他任何东西引用的对象的封闭循环的一部分时),它就会变成“悬空”。这是可能的,因为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
于 2012-09-29T14:07:10.800 回答