【问题标题】:Possible to get "value of address" in python?可以在python中获得“地址值”吗?
【发布时间】:2019-10-19 23:02:18
【问题描述】:

在下面,我可以看到,在 python 中添加整数时,它会添加整数,将结果值分配给新的内存地址,然后将变量设置为指向该内存地址:

>>> a=100
>>> id(a)
4304852448
>>> a+=5
>>> id(a)
4304852608

有没有办法查看(旧)内存地址 4304852448 (0x10096d5e0) 处的值是什么?例如:value_of(0x10096d5e0)

【问题讨论】:

  • 垃圾回收发生时为什么会覆盖内存位置?那会有什么用?此外,这不是 Python 语言规范的一部分,因此您可能希望为您所指的特定实现添加标签(可能是 CPython)。
  • @a_guest -- 谢谢。是的,我只是想查看垃圾收集之前/之后的地址等等。

标签: python cpython python-internals


【解决方案1】:

它将整数相加,将结果值分配给新的内存地址

没有; 表示结果值的对象不同的内存地址。通常,此对象是动态创建的,但特别是对于整数(不可变,并且对于应用类似优化的一些其他类型),该对象可能已经存在并可以重复使用。

有没有办法查看(旧)内存地址 4304852448 (0x10096d5e0) 处的值是什么?

这个问题不是很好提出的。首先,在这种情况下,“内存地址”是虚拟化的,可能不止一次。其次,在 Python 模型中,地址没有“值”。它们可能是对象的位置,而这些对象又代表值。

也就是说:在前一个id(a) 的位置,当且仅当它没有被垃圾回收时,旧对象仍然存在。为此,保留对该对象的一些其他引用就足够了。 (垃圾回收的时机由实现定义,但参考CPython实现是通过引用计数来实现垃圾回收的。)

一般来说,您无权直接检查底层内存(除非可能有某种具有适当权限的进程间谍),因为 Python 并不是一种低级语言。 (正如@xprilion 的回答,CPython 实现通过ctypes 提供了一个较低级别的内存接口;但是,那里的代码实际上是在进行不安全的转换。)

如果你这样做了(假设是 CPython),你将不会在第一次调用 id(a) 指示的内存位置中看到整数 100 的二进制表示 - 你会看到PyObject 结构的第一个字用于在 C 代码中实现对象,它(如果我正确阅读 it)将是指向下一个活动堆对象的指针(全部连接在双向链表中) .

一旦它被垃圾回收,该内存的内容再次未定义。它们依赖于实现,甚至专门针对 C 实现,它们依赖于标准库 free() 对内存的处理。 (通常它不会被触及,因为没有理由将其归零并且这样做需要时间。调试版本可能会将特殊值写入该内存,因为它有助于检测内存损坏。)

【讨论】:

  • 我同意我的回答中不安全的部分。它可能在这里回答了确切的问题,但对于爱好者来说阅读这个答案以及了解幕后发生的事情也很重要。谢谢!
【解决方案2】:

您正试图取消引用内存地址,就像 C/C++ 中使用的指针一样。以下代码可能会对您有所帮助 -

import ctypes

a = 100
b = id(a)

print(b, ": ", a)

a+=5
print(id(a), ": ", a)

print(ctypes.cast(b, ctypes.py_object).value)

输出:

140489243334080 :  100
140489243334240 :  105
100

上面的例子确立了a之前地址中存储的值保持不变。

希望这能回答这个问题。阅读@Karl 的答案,了解有关后台发生的更多信息 - https://stackoverflow.com/a/58468810/2650341

【讨论】:

  • 你说得对,在 Python 的参考 C 实现中实际上可以访问原始内存。我已经编辑了我的答案以反映这一点。
猜你喜欢
  • 2020-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多