它的全局变量的地址对于程序的不同运行是相同的

Is address of global variables the same for different runs of the program?

本文关键字:程序 运行 地址 全局变量 于程序      更新时间:2023-10-16

考虑以下代码片段

int i=10;
int main()
{
    cout<<&i;
}

一旦为程序生成了exe,对于程序的不同运行,输出是否相同?假设操作系统支持虚拟内存

编辑:这个问题是特定于全局变量存储在数据段。因为这是第一个全局变量,地址应该是相同的还是不同的?

如果ASLR被禁用,您总是得到相同的地址。如果启用ASLR,您将获得不可预测的地址。

虚拟地址将由链接器决定。物理地址将随每次加载而变化。

简单回答:看情况:-)

如果你的操作系统总是在相同的环境下启动一个程序,并且虚拟内存范围看起来总是相同的,那么输出应该总是相同的。

但是如果你在不同的硬件上运行相同的操作系统(可能有不同数量的可用内存),它可能会导致不同的地址,但通常地址也是相同的,独立于硬件。

但是你不应该期望结果是相同的!简而言之:不要考虑程序中数据的虚拟地址或真实地址。这是由编译器、操作系统和一些库控制的。所以忽略它吧!

简短的回答:在x86-64机器上运行的用户模式程序:不,您不应该假设无论出于何种原因


长话短说:地址可能是相同的,但这绝对不能保证(至少在x86_64操作系统和机器上运行的程序上)。

我读到一些关于虚拟/物理内存的混淆,以及为什么地址是"随机",所以让我从高层次的角度解释一些事情:

针对x86_64架构和操作系统(让我们说Windows),你甚至不能假设操作系统本身会将其所有组件加载到相同物理位置的内存中(一些例外的旧引导加载程序约定在000:7 c00h,我不知道这在UEFI环境中是如何工作的)。

在段(是否使用取决于操作系统,通常Windows只是为用户模式和内核模式设置了一些普通段)被放置之后,一旦你切换到保护模式(或长),你就无法控制操作系统如何管理虚拟内存机制,它隐藏了复杂的层和mmu相关的操作,给你的进程一个自己的地址空间。

另外还有安全措施:链接器可能决定你的可执行文件的基址,但在其他情况下,当ASLR被激活时,操作系统可以随意移动它的模块和你的可执行文件,因为它喜欢安全的目的。

结论:除非你在处理非常低级的东西(例如物理地址或直接写入外部设备的内存区域),否则你绝对不应该依赖变量的地址在不同的运行中是相同的。没有保证