A raw computer basically just has memory with physical addresses starting at 0, right? Then someone could write assembly code (such as a BIOS) and actually put a value at 0.
Now if there is a BIOS that starts the computer, then someone could write a loader for an operating system. Can that person decide to move actual values to position 0 in the memory in assembly language?
What if they use C or C++? Can they have a pointer with value 0 and use it to access the first memory location? Does that need a specially adapted compiler?
And then the operating system enters the scene. It has a memory manager which is called by malloc
to get more memory. Could an operating system be written which can simply use 开发者_开发技巧null pointers as normal pointers, but otherwise behaves exactly like Linux, and then if someone compiles a C program with a normal, unmodified GCC for it, a null pointer wouldn't lead to a segmentation fault?
The null pointer in C and similar languages is just a convention, to allow an easy to check for indication that a pointer doesn't point to anything valid. There is nothing in the computer that physically stops anything from storing data at memory location 0. In fact, the C standard doesn't even state that the null pointer must have all bits zero or correspond to memory location 0, just that it must be what you get from (void *)0
.
malloc
and similar functions cannot return a null pointer as a valid memory location, because a return of a null pointer is specifically defined to indicate failure.
Now, to support this extremely common usage of the null pointer in C, some operating systems will specifically not map or otherwise set a trap for the memory location corresponding to the null pointer so any accidental accesses will immediately raise a segmentation violation or the like. Operating systems do exist that do not do this, of course.
While the NULL pointer is represented in C source code as a 0
, there is no requirement that the underlying bit pattern actually has to be 0. It just has to be distinguishable from non-NULL pointers. There are examples of architectures where it isn't zero under the covers.
It's the C implementation itself that decides what a NULL is.
You should also realise that modern operating systems (well, those that do virtual memory) have a disconnect between a process virtual address space and the underlying physical memory.
Read this Why does Linux program that derefrences (char*)0 not always segfault? it's at least half of your response :-) And this http://wiki.debian.org/mmap_min_addr The first part, about the vulnerabilities that where possible before the "fixing" of mmap_min_addr. And this http://eparis.livejournal.com/606.html, with a story of the vulnerability.
So yes, it's possible to map a page to address 0 and put code there. Your system will be weaker to errors in programs, but "perfect" programs will work in the same way as before. As for the question "what would happen if a program access the segment 0"... Well... Whatever you want...
But I think you don't exactly comprehend how the protected memory of "modern" processors work. Each process can see a different block of memory mapped to an address, and some processes can "write" to this page, and some can only "read" (and some can execute).
Linux (or any "normal" processes and virtual-memory OS) leaves the lowest addresses unmapped, specifically to gain detection of null-pointer bugs. consider the following example:
#include <unistd.h>
#include <sys/mman.h>
int main() {
char *p = mmap(0,4096,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_SHARED|MAP_FIXED,-1,0);
if (p == MAP_FAILED) return 1;
p[0] = 'x';
p[1] = '\n';
write(1,0,2);
return 0;
}
this works on pre-selinux systems (prints "x"), though on my desktop with selinux disabled, it only works as root, not a normal user. but the point is that you generally have control of everything in your virtual address space. if you really want to put something at 0, you can, though you might run into, for instance, code that refuses to deal with a string at 0.
精彩评论