存储在第一个存储器地址中的内容是什么?操作系统?为什么我不能打印内容?

时间:2016-05-09 01:30:33

标签: c

所以这完全是出于我自己的好奇心,我想通过每个内存地址从0x000000一直到我硬盘的最后一个地址。所以我写了这个C片段:

#include <stdio.h>

int main() {
        void* ptr = 0x00000;
        int x = 0;
        while ( x == 0 ) {
                puts("hi");
                printf("%p\t%c\n",ptr,*(int*)ptr);
                ptr++;
        }
}

&#34;喜&#34;我在segfault之前只打印一次。什么存储在0x000000,为什么我无法访问它?

2 个答案:

答案 0 :(得分:4)

那里什么都没有。空指针指向任何东西,这就是它崩溃的原因。你在做*NULL。事实上,在当前使用的几乎任何平台上,NULL被定义为0(虽然注意到标准实际上并没有保证这一点,并且可能存在一些不同的平台,它有所不同)。

无论如何你都无法访问随机内存。它指向哪里? 你的地址完全无效,在这种情况下你会得到一个段错误,或者它指向其他程序的内存,你不能访问它,你仍然会遇到段错误。

在现代系统中,你甚至没有直接指向内存。地址是虚拟的。如果地址是您的,并且有意义,操作系统将使用page table将其转换为真实地址。如果地址不是您的,则会出现段错误。

如果你有一个非常古老的系统(想象一个8位微型)或一个简单的微控制器,没有虚拟内存或多任务或类似的东西,那么你实际上可以做到这一点。但在现代系统中,你做不到。

答案 1 :(得分:1)

首先,你不是在看操作系统; 你正在查看自己进程的已分配内存。 用这种方法你能看到的最多 是你的过程的形象 (可能包括您链接到的任何图书馆)。

其次,除非你做的事非常特别, 您正在使用virtual memorymarinus says。 您的进程中的虚拟地址0x001000 可能映射到物理地址0x01234000; 虚拟地址0x002000可能映射到物理地址0x42017000。 某些虚拟地址可能根本无法映射到任何地方 - 考虑一下,在32位机器上,你可以有2个 32 地址。 这是4 GiB - 没有多少计算机甚至拥有那么多的物理内存。 (我们甚至不考虑64位机器!) 即使系统有4 GiB的物理内存, 它不会全部映射到您的虚拟地址空间, 因为它会包含其他进程的内存(是的,内核内存)。

正如marinus所提到的,值为0的指针是空指针。 C Programming Language Specification, 第6.3.2.3节“指针”第3段说,

  

值为0的整数常量表达式,   或者这样的表达式转换为void *类型,   被称为空指针常量。   如果将空指针常量转换为指针类型,   结果指针,称为空指针,   保证比较不等于指向任何对象或函数的指针。

第二句话意味着什么都没有 在空指针地址(0地址), 因为,如果那里有东西, 那么指向该对象的指针将等于空指针。 因此, C运行时环境设置虚拟→物理内存映射 像这样的东西:

Virtual Memory Map

(建立在the Wikipedia page中的那个), 其中虚拟地址0始终配置为不映射到任何内容。

C语言并不总是指定此行为。 最近25-30年前, 程序可以访问虚拟内存位置0 - 特别是在16位系统上, 和内存管理架构不够复杂的机器 允许系统使内存页面0无法访问 而不会牺牲大部分虚拟地址空间。