#include <iostream>
using namespace std;
int main(void)
{
int *ptr = new int;
cout << "Memory address of ptr:" << ptr << endl;
cin.get();
delete ptr;
return 0;
}
每次运行此程序时,我都会获得ptr
的相同内存地址。为什么呢?
答案 0 :(得分:14)
[注意:我的回答是假设你正在使用一个使用虚拟内存系统的现代操作系统。]
由于虚拟内存,每个进程都在自己唯一的地址空间中运行,该地址空间独立于任何其他进程,不受任何其他进程的影响。您从new
获得的地址是虚拟地址,并且由您的编译器new
选择执行的任何内容生成。 * 没有这不可能是确定性的。
另一方面,与您的虚拟内存地址关联的物理地址每次都很可能会有所不同,并会受到各种因素的影响。此映射由操作系统控制。
<小时/> *
new
可能是根据malloc
实现的。
答案 1 :(得分:6)
我说这主要是巧合。因为内存分配器/操作系统可以为您提供它想要的任何地址。
您获得的地址显然不是随机的(并且高度依赖于其他操作系统因素),因此通常会在行中多次获得相同的(虚拟)地址。
例如,在我的机器上:使用VS2010编译的Window 7,我得到了不同运行的不同地址:
00134C40
00124C40
00214C40
00034C40
00144C40
001B4C40
答案 2 :(得分:1)
这是您环境的工件。 cin.get()向我建议您在Visual Studio中编译和执行,它提供了一个异常可预测的运行时环境。当我在linux上编译并运行该代码时,两次执行给出了两个不同的地址。
ETA:
在评论中,您表示期望不同的进程可以获得相同的内存地址,并且该地址将无法访问您的程序。在任何现代操作系统中都不是这样,因为操作系统为每个进程提供虚拟内存地址空间。
只有操作系统才能看到真正的硬件地址,并维护每个程序的虚拟内存映射,将虚拟地址重定向到物理地址。因此,任意数量的不同进程可以将数据保存在同一个虚拟地址中,而操作系统会将该地址映射到每个进程的单独物理地址。
这保证了进程A无法读取或写入进程B正在使用的内存,而没有启用此类访问的特殊规定(例如通过指示操作系统将某些进程中的某些虚拟内存映射到同一物理内存)。它允许操作系统使不同类型的内存硬件对程序透明。
它还允许操作系统将程序的数据移到其后面,以优化系统性能。 经典示例:将一段时间未使用的数据移动到硬盘上的特殊文件中。这有时称为页面文件。
内存映射通常分为页:一定大小的连续内存块(页面大小)。虚拟地址空间页面中保存的数据通常在物理内存中也是连续的,但如果数据在页面边界上运行,则在虚拟内存中看起来连续的信息可以很容易地分开。如果C / C ++程序进入未定义的行为,它可能会尝试访问操作系统尚未映射到物理内存的页面中的内存。这将导致操作系统生成错误。