0

What is the highest number Python 2.6's x86 id() function can return?

I presume the ceiling must be the amount of memory any 32-bit application can see which must be: 232, i.e. 4294967296?

(Which would be fine as I have to fit this value in a C# type for which UInt32 or the CLS-compliant Int64 would suffice, which it the reason for my concern, though irrelevant to the question.)

But what if a I am running on Windows x64 with more than 2GB of memory say 32GB of memory - is it possible for Python's id() function, even though the Python interpreter itself is x86, to return a value higher then 232???

I am guessing it comes down to the Python interpreter's view of the machine - I imagine WoW64 translates 64-bit memory addresses to 32-bit addresses - but I am only guessing - I need to be sure!

Zero Piraeus
  • 56,143
  • 27
  • 150
  • 160
markmnl
  • 11,116
  • 8
  • 73
  • 109
  • Why can't the id() function be 2**63 + , for example? – President James K. Polk Jan 13 '12 at 01:38
  • huh? id() returns the memory address. my question is whether it can be higher than 2^32 - i suspect not because the interpreter is a 32bit app - but I dont know... – markmnl Jan 13 '12 at 01:51
  • 5
    In practice it returns the memory address, but it doesn't have to return the memory address to comply with `id()` contract. – President James K. Polk Jan 13 '12 at 01:55
  • id() does and only ever will return the memory address in the version I am using – markmnl Jan 13 '12 at 02:00
  • 1
    In that case I would guess your conjecture is correct. I don't see any way for a 32-bit bit app to have anything but a 32-bit "view" of memory, even if actual physical addresses are larger. – President James K. Polk Jan 13 '12 at 02:09
  • 1
    I am confused as to why you "need to be sure of this"?. The only thing you are supposed to use the return value of id() for, is identifying objects. It shouldn't really matter to you whether it is large, small, a memory address or not, as long as it is guaranteed to be the same unique number, for a given object, during the objects lifetime. – AHM Jan 22 '12 at 17:37
  • The reason is in my question: "... I have to fit this value in a C# type for which UInt32 or the CLS-compliant Int64 would suffice, which is the reason for my concern...", nonetheless the question is academic. – markmnl Jan 25 '12 at 01:03

5 Answers5

18

From the linked documentation:

Returns (...) an integer (or long integer)

In Python 2.x on amd64, a long integer is an integer larger than 64 bits. In any case, in Python, integers are unbounded. Therefore, id can return arbitrarily long values.

If you must know a definite maximum value, you may assume that the available memory on your platform is an upper boundary for the size of the integer you get. Therefore, I'd specify 2232 for 32 bit, and 2264 for 64 architectures. In the case of an x86 python implementation, one can therefore place an upper boundary at 2232 with reasonable confidence.

cpython (the most popular python implementation) will indeed return a memory addresses (builtin_id in Python/bltinmodule.c):

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

This will be a 32 bit/64 bit value, but the behavior is an implementation detail, as explicitly stated in the docs. By definition, a programmer must not rely on implementation details.

I strongly doubt that there is a legitimate use case for ever using IDs, much less transferring them to another program. Instead, you should use a custom object table, or just transfer a set. If you intend to use Python in conjunction with C#, ironpython allows you to do so in the same code.

phihag
  • 278,196
  • 72
  • 453
  • 469
  • i know - that doesnt answer my question of whether the x86 version can ever return a long higher than 2^32 i.e. can it address more than 2GB of memory... – markmnl Jan 13 '12 at 01:53
  • 4
    @Fëanor I'm pretty sure it does, with: `Yes, and it can even be higher than 2^64`. As marked in the doc, `id` returning an address is an *implementation detail* and therefore must not be relied upon. – phihag Jan 13 '12 at 01:54
  • i know the it can in the sense it could - but practically the x86 cannot bacause it should not be able to address memory higher then 2GB, surely – markmnl Jan 13 '12 at 01:56
  • 2
    Updated my comment. `id` doesn't have to return a memory address, and assuming that it does is wrong. – phihag Jan 13 '12 at 01:58
  • it will only ever return the memory address in the version i am using - assuming it wont in a future version is not a worry for me – markmnl Jan 13 '12 at 02:02
  • That's because you're using cpython 2.x on x86. If you change any three of these parameters, you'll get different results. On a related note: Why aren't you using [IronPython](http://ironpython.net/)? And why do you need the results of `id(...)` anyways? – phihag Jan 13 '12 at 02:06
  • im sorry i dont have time to get sidetracked. can you show me where you got the info if you use python 2.x on x64 you will get different results from id() – markmnl Jan 13 '12 at 02:08
  • 2
    No offense, but I don't think I can answer your question if you're not willing to get "sidetracked". *You're on the wrong track*. Or, to quote [Raymond Chen](http://blogs.msdn.com/b/oldnewthing/archive/2011/11/04/10233798.aspx): You have broken down the problem into two parts, one easy and one impossible. Note that calling the interpreter `python` is misleading. You probably mean cpython, which is one python implementation. I inspected the memory with gdb and saw the results of `id` in cpython 2.7 are nowhere near the allocated memory. – phihag Jan 13 '12 at 02:16
  • Updated the answer with a summary of the relevant points of the discussion in the comments. Note that the behavior of cpython *is* architecture-independent, and therefore a memory address on x64 as well. – phihag Jan 13 '12 at 03:08
  • why do you think 2^2^32 for 32 bit architectures?? – markmnl Jan 13 '12 at 05:27
  • 1
    Because 2^32 is an upper boundary for the memory one process can allocate on a 32bit arch, and therefore 2^2^32 is an upper boundary for the largest number you can represent with Python's `int`. – phihag Jan 13 '12 at 13:01
  • If "2^32 is an upper boundary for the memory one process can allocate on a 32bit arch" then wouldnt that be the answer?? What has the max value of int got to do with it?? – markmnl Jan 14 '12 at 03:21
  • 1
    @Fëanor Since 2^32 is an upper boundary for the memory one process can allocate, it's an upper boundary for the number of bytes used to store an `int`. Since `id` returns an arbitrary `int`, 2^2^32 is an upper boundary for the largest number it can practically return. You keep assuming that `id` returns a memory address. As Ben and I wrote repeatedly, that's an **implementation detail** of cpython you must not rely on. – phihag Jan 14 '12 at 10:36
  • id does not return an arbitrary int - it returns either an int or a long which as you know has no upper limit. Why do you say "2^2^32 is an upper boundary for the largest number it can practically return"? – markmnl Jan 16 '12 at 00:16
  • 3
    @Fëanor, I think phihag has answered the question you asked, "What is the highest number Python 2.6's x86 id() function can return?" The answer is one of: an integer, a long integer, or 2^2^32. But you seem unwilling to accept those answers. I don't think you'll get better answers, unless you ask a different question. – Jim DeLaHunt Jan 19 '12 at 15:49
  • "The answer is one of: an integer, a long integer" - that is the the answer from the documentation what id() can possibly return, "2^2^32" I have asked where he got it from but he hasnt replied - it seems to be a guess. You misquoted my question it is: "What is the highest number Python 2.6's x86 id() function on Windows x64 can return?". He has not answered the later part - he has provided circumstantial information I already knew, made a guess which he has not given the basis for and told me I am doing the wrong thing whith out knowing what I am doing! – markmnl Jan 22 '12 at 06:10
  • 1
    Updated the answer with an explanation for the boundary. I don't mean to offend you, but if you look at the history of comments, you kept asking the same question, and didn't clarify what part of the rationale for 2^2^32 you didn't understand. And I know that you're intending to use `id` in another program. That is a bad idea not only since Python integers (`int` or `long` in 2.x) do not fit into any fixed-size bitfield (although one can give upper boundaries), but also since your program will break in different python versions or implementations if you rely on specific `id` values. – phihag Jan 22 '12 at 12:36
  • If cpython is returning addresses as Ids, the limit is actually a bit smaller than 2^31 on x86, since you can't allocate addresses in kernel space, nor can you use addresses < 0x10000 (at least on Windows). – Ana Betts Jan 23 '12 at 00:16
  • Thanks Paul, DRH has said is much in an answer so I have marked that correct. – markmnl Jan 23 '12 at 00:25
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')

i think in practical the max value the id() can achieve is 2**32 but in reality it never reaches such high number. I tried the above code in the 32 bit architecture . please let me know if i made any mistake in understanding your question.

4294967296L is the 2^32 and max id() i reached is 1460876200.

blackwind
  • 182
  • 1
  • 10
1

Your guesses seem reasonable, but I have no idea if they're correct.

If you need to rely on behaviour that is an implementation detail (i.e. isn't specified in the docs), and you need to be sure, then I guess the only thing to do is read the source code for the version you're using and find out what it does.

Ben
  • 68,572
  • 20
  • 126
  • 174
  • I am afraid it may be more of an OS issue and in particular how it handels 32 bit apps on a 64 bit machine. – markmnl Jan 16 '12 at 00:21
  • 2
    If you are that certain that `id` will always return a memory address, but you're not sure whether a memory address will fit into 32 bits, then your question has nothing to do with Python and you should go read the 32 bit compatibility information for your 64 bit OS. However, I'm 99% a 32 bit C program compiled to use 32 bit pointers isn't going to be able to fit a number outside the range of a 32 bit integer in a pointer. So the OS will either give it 32 bit pointers, or fail to run it. – Ben Jan 16 '12 at 02:46
1

Windows will run an application in the environment (32 or 64 bit) that it was compiled for, not the CPU it is running on. E.g., an x64 computer running Windows 7 will run 32-bit python in a 32-bit environment.

So, running python compiled for x86 will always use a 32-bit address space, which means that id() will always return a value that maps to a unique 32-bit pointer. (Note that the implementation may do some weird stuff like salting the pointer or using 64-bits or some crazy stuff like that.)

MSN
  • 53,214
  • 7
  • 75
  • 105
1

Assuming the documentation for id() is correct and CPython (x86) returns the address of the object, the maximum value that can be returned is 232-1 (4294967295). This can be demonstrated in a simple C program:

#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;
}

This is true regardless of the underlying OS, an application compiled with a 32-bit pointer type can only specify addresses between 0 and 232-1. Note that the address visible in the application may not correspond to a particular physical memory address, due to the use of virtual memory.

DRH
  • 7,868
  • 35
  • 42
  • Most operating systems reserve the top bit (i.e > 0x7FFFFFFF) as kernel memory, so you actually will only get somewhat less then 2^31 (since parts of the VA space are also reserved for Python itself, illegal addresses, etc) – Ana Betts Jan 23 '12 at 00:52