1

正如问题所问:

如果你遍历内存,或者选择随机内存地址分配随机数据,会发生什么?

当然,对此有一些保护措施,但我不打算尝试以防万一。

我知道这似乎是一个幼稚的问题,但这是出于好奇!

4

3 回答 3

4

如果您尝试访问未分配给您的进程的内存地址,或者您违反了访问控制(例如尝试写入标记为只读的地址),您很可能会触发陷阱(Unix 上的分段违规, Windows 上的内存保护错误)。

如果您将随机数据写入内存的某个可访问部分,您可能会破坏程序使用的数据结构,可能会覆盖堆栈的关键部分或堆的簿记数据。这将导致程序的行为不可预测,并且可能会或可能不会导致陷阱。

于 2013-05-18T09:07:36.267 回答
3

我真的取决于操作系统。

在所有现代操作系统中,内存确实受到保护,因为只有您的应用程序实际可用的内存才被赋予虚拟地址转换(您的应用程序可能与另一个不同类型的应用程序具有相同的虚拟地址,但使用不同的物理地址)。

访问未“映射”的内存(虚拟地址没有转换为物理地址)将导致“页面错误”,然后操作系统会检查内存是否真的应该在那里(它可能已被换出到磁盘),如果这没有产生任何结果,它将导致操作失败,这通常会结束您的程序。

于 2013-05-18T09:07:38.647 回答
3

我认为满足您对地址空间的好奇心的最佳方法是检查某个进程的内存映射。例如,如果您使用的是 Linux,请尝试:

$ cat /proc/2480/maps 
08048000-08049000 r-xp 00000000 08:05 8669698         /tmp/test
08049000-0804a000 r--p 00000000 08:05 8669698         /tmp/test
0804a000-0804b000 rw-p 00001000 08:05 8669698         /tmp/test
f759f000-f75a0000 rw-p 00000000 00:00 0
f75a0000-f7740000 r-xp 00000000 08:05 4465182         /lib32/libc-2.15.so
f7740000-f7741000 ---p 001a0000 08:05 4465182         /lib32/libc-2.15.so
f7741000-f7743000 r--p 001a0000 08:05 4465182         /lib32/libc-2.15.so
f7743000-f7744000 rw-p 001a2000 08:05 4465182         /lib32/libc-2.15.so
f7744000-f7748000 rw-p 00000000 00:00 0
f775e000-f7760000 rw-p 00000000 00:00 0
f7760000-f7761000 r-xp 00000000 00:00 0               [vdso]
f7761000-f7781000 r-xp 00000000 08:05 4465203         /lib32/ld-2.15.so  
f7781000-f7782000 r--p 0001f000 08:05 4465203         /lib32/ld-2.15.so  
f7782000-f7783000 rw-p 00020000 08:05 4465203         /lib32/ld-2.15.so  
ffc67000-ffc88000 rw-p 00000000 00:00 0               [stack]

您感兴趣的某个进程的 PID在哪里2480(在我的情况下,我只是运行了一个测试程序)。

第一列和第二列是地址空间的范围;指针值基本上。这些范围被称为“映射”,因为它们建立了“映射”的地址空间范围,这意味着您可以读取、写入和/或执行它。操作系统设置每个映射以对应一些内存和/或文件。如果您的进程试图读取、写入或执行不在这些范围之一内的任何指针,程序将出现段错误。请注意,指针值“0”没有映射——这是操作系统保证取消引用NULL指针将使程序崩溃的方式。

对于这些范围内的任何指针值,会发生什么取决于该映射的内存保护(r可读、w可写、x可执行)以及在该地址映射的内容。你会注意到我的程序本身 ( /tmp/test) 被映射到地址空间;如果我从这些区域读取数据,我将读取程序的代码和数据。共享库中的其他范围映射,最后一个映射是堆栈。

当然,这一切都假设您在带有MMU的受内存保护的操作系统下运行程序;MMU 是让操作系统设置这些特定范围的原因,这些范围意味着不同的事物。在没有 MMU 的 CPU 上,读取内存只会读取所有内存本身的物理内容。

于 2013-05-18T10:01:26.943 回答