什么是最高数量的Python 2. * x86(即32位)id()函数在Windows x64上可以返回?

时间:2012-01-13 01:24:17

标签: python windows python-2.6 wow64

Python 2.6的x86 id()函数可以返回的最高数字是什么?

我认为上限必须是任何32位应用程序可以看到的内存量必须是:2 32 ,即4294967296?

(这可以,因为我必须在UInt32或符合CLS的Int64就足够的C#类型中使用此值,这是我关注的原因,尽管与此无关问题。)

但是如果我在Windows x64上运行的内存超过2GB并说内存为32GB,那么Python的id()功能是否可行,即使Python解释器本身是x86,返回一个高于2 32 ???

的值

我猜它归结为Python解释器对机器的看法 - 我想WoW64将64位内存地址转换为32位地址 - 但我只是猜测 - 我需要确定!

5 个答案:

答案 0 :(得分:18)

来自linked documentation

  

返回(...)整数(或长整数)

在amd64的Python 2.x中,长整数是大于64位的整数。无论如何,在Python中,整数是无界的。因此,id可以返回任意长的值

如果必须知道确定的最大值,则可以假设平台上的可用内存是您获得的整数大小的上限。因此,我为32位指定了2 2 32 ,对于64种架构,我指定了2 2 64 。在x86 python实现的情况下,可以合理放心地将上边界置于2 2 32

cpython(最流行的python实现)确实会返回一个内存地址(builtin_id中的Python/bltinmodule.c):

static PyObject * builtin_id(PyObject *self, PyObject *v) {
    return PyLong_FromVoidPtr(v);
}

这将是一个32位/ 64位值,但行为是实现细节,正如文档中明确说明的那样。根据定义,程序员不能依赖于实现细节。

我强烈怀疑有一个合法的用例永远使用ID,更不用说将它们转移到另一个程序了。相反,您应该使用自定义对象表,或者只是传输一组。如果您打算将Python与C#结合使用,ironpython允许您使用相同的代码执行此操作。

答案 1 :(得分:2)

def func(n):
    max=0L
    for i in range(n):
        x=id(i)
        if x > max : max=x
    return max

for i in range(32):
    x=0L
    try:
        x=func(2**i)
        print '{0: 10}{1: 15}{2: 15}'.format(i,2**i,x)
    except:
        print '{0: 10}{1: 15}{2:>15}'.format(i,2**i,'error')

我认为实际上id()可以达到的最大值是2 ** 32,但实际上它永远不会达到如此高的数值。我在32位架构中尝试了上述代码。如果我在理解你的问题时犯了错误,请告诉我。

4294967296L是2 ^ 32,我达到的最大ID()是1460876200.

答案 2 :(得分:1)

你的猜测看似合理,但我不知道它们是否正确。

如果您需要依赖于实现细节的行为(即未在文档中指定),并且您需要确定,那么我想唯一要做的就是阅读您正在使用的版本的源代码,并找出它的作用。

答案 3 :(得分:1)

Windows将在编译的环境(32位或64位)中运行应用程序,而不是运行它的CPU。例如,运行Windows 7的x64计算机将在32位环境中运行32位python。

因此,运行为x86编译的python将始终使用32位地址空间,这意味着id()将始终返回映射到唯一32位指针的值。 (注意,实现可能会做一些奇怪的事情,如盐化指针或使用64位或类似的一些疯狂的东西。)

答案 4 :(得分:1)

假设id()的文档正确且CPython(x86)返回对象的地址,则可返回的最大值为2 32 -1(4294967295)。这可以通过一个简单的C程序来证明:

#include <stdio.h>

int main(void) {
    void* p = 0;          // specify a pointer at 0
    p = ~p;               // invert all bits
    uintptr_t x = p;      // convert to an integer type fo the same size
    printf("%lu\n", x);
    return 0;
}

无论底层操作系统如何,都是如此,使用32位指针类型编译的应用程序只能指定0到2 32 -1之间的地址。请注意,由于使用了virtual memory,应用程序中可见的地址可能与特定的物理内存地址不对应。