繁体   English   中英

为什么指针/变量内存地址不会改变?

[英]Why do pointer / variable memory addresses not change?

#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的相同内存地址。 为什么?

[注意:我的回答是假设你正在使用一个使用虚拟内存系统的现代操作系统。

由于虚拟内存,每个进程都在其自己唯一的地址空间中运行,该地址空间独立于任何其他进程并且不受任何其他进程的影响。 您从new获得的地址是一个虚拟地址 ,由您的编译器执行的new选择生成。 *没有理由这不是确定性的。

另一方面,与虚拟内存地址关联的物理地址每次都很可能会有所不同,并会受到各种因素的影响。 该映射由OS控制。


* new可能是以malloc

我会说这主要是巧合。 因为内存分配器/操作系统可以为您提供它想要的任何地址。

您获得的地址显然不是均匀随机的(并且高度依赖于其他OS因素),因此通常在行中多次获得相同(虚拟)地址。

例如,在我的机器上:使用VS2010编译的Window 7,我得到不同运行的不同地址:

00134C40
00124C40
00214C40
00034C40
00144C40
001B4C40

这是您的环境的工件。 cin.get()向我建议你在Visual Studio中编译和执行,它提供了一个异常可预测的运行时环境。 当我在我的linux上编译并运行该代码时,两次执行给出了两个不同的地址。

ETA:
在评论中,您表示期望不同的进程可以获得相同的内存地址,并且该地址将无法访问您的程序。 在任何现代操作系统中都不是这种情况,因为操作系统为每个进程提供虚拟内存地址空间。

只有操作系统才能看到真正的硬件地址,并维护每个程序的虚拟内存映射,将虚拟地址重定向到物理地址。 因此,任意数量的不同进程可以将数据保存在同一虚拟地址中,而操作系统将该地址映射到每个进程的单独物理地址。

这保证了进程A不能读取或写入进程B正在使用的存储器而没有启用这种访问的特殊规定(例如通过指示OS将某些进程中的某些虚拟存储器映射到同一物理存储器)。 它允许操作系统使不同类型的内存硬件对程序透明。

它还允许操作系统将程序的数据移到其后面,以优化系统性能。 经典示例:将一段时间未使用的数据移动到硬盘上的特殊文件中。 这有时称为页面文件

内存映射通常分为多个页面 :一定大小的连续内存块( 页面大小 )。 虚拟地址空间页面中保存的数据通常在物理内存中也是连续的,但如果数据在页面边界上运行,则在虚拟内存中看起来连续的信息可以很容易地分开。 如果C / C ++程序进入未定义的行为,它可能会尝试访问操作系统尚未映射到物理内存的页面中的内存。 这将导致操作系统生成错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM