开发者

Question about the NULL-Pointer Assignment Partition in a process' address space

I am reading < Windows via C/C++ 5th edition > and below is some quotation:

Each process' virtual address space is split into partitions. On x86 32-Bit Windows, the partition of 0x00000000 - 0x0000FFFF (inclusive) is called NULL-Pointer Assignment Partition. This partition is set aside to help programmers catch NULL-pointer assignments. If a thread in your aprocess attempts to read from or write to a memory address in this partition, an access violoation is raised.

I am wondering, why do we have to use a range of address space instead of just the value 0 to catch NULL-pointer assignments? AFAIK, NULL开发者_StackOverflow中文版 equals 0. So what's the consideration behind this design? Is there anything else reside in this range that user shouldn't touch? Or does NULL not necessarily equal 0?

Many thanks.


All modern operating systems cleverly implement a null pointer dereference check with no execution overhead using the virtual memory management hardware. The 0th 4 KB page (or in this case, 0-15th pages (totalling 64 KB)) is set up so any data read or write or instruction execution at address 0 (or 0x00000FFF or 0x0000FFFF for that matter) instantly results in an access violation exception.

Let me put it a different way. Trapping null pointer dereferences to 0, but allowing data references to (say) address 1, would be prohibitively expensive -- since you could not use the page-granularity VM hardware, it would instead be necessary to perform a null pointer compare and branch sequence before many pointer dereferences. By making the first page or first few pages inaccessible, this check can be done "for free" in the VM hardware. The downside is you can't use those first page(s) for anything else.

(In theory, a sufficiently optimizing compiler could then be employed to determine which pointer dereferences could not possibly be null pointer dereferences, but until such clever compilers appear, the unmapped 0 page trick will have to do.)

So why is the Windows (post Win98) null pointer assignment partition 64 KB instead of the minimum necessary 4 KB? Wyzard's answer makes a good case for catching null pointer array index errors as well.

* Late update: RE: why 64 KB? -- I asked someone who ought to know on the Windows Core team, and they said it is probably a 64 KB region because Windows keeps certain memory management structures at a 64 KB allocation granularity. Why is that? I don't know, but perhaps Raymond Chen has the answer: http://blogs.msdn.com/b/oldnewthing/archive/2003/10/03/55239.aspx. Wow. *


Within the C or C++ language, NULL always equals 0, but 0 as a pointer value in the source code doesn't necessarily correspond to all zero bits in the compiled binary. However, on Windows I believe a null pointer really is all zero bits.

The reserved space is probably to help catch things like myarray[n] where myarray is null, or mystruct->myfield where mystruct is null. The address being accessed isn't necessarily exactly where the pointer points, it may be somewhere after it.


The range is necessary to ease detection of bugs caused by dereferencing null and close to null pointers. For example:

int startOffset = 1000; //start at 1000th element;
char* buffer = obtain();// happens to be null
for( int i = startOffset; buffer[i] != 0; i++ ) {
   //do stuff
}

Note thet null pointer is never dereferenced in the above sample. Yet since buffer is a null pointer resulting addresses are close to null and dereferencing them can be easily caught using the "partition" technique.


A range is required because when a pointer to a struct or class element is dereferenced the actual memory accessed is going to be the pointer, plus the offset of the member in the struct.

struct Foo {
    int a;
    inb b;
}* Bar = 0;

Bar->b = 0;

On int = 32bit compilers, the 'b' member will be 4 bytes into the struct, so Bar->b will attempt to access the address 0x00000004.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜