初始化后的内存地址相同

问题描述 投票:3回答:2

我正在努力创建没有rand()的随机数字(只是因为我喜欢尝试的东西)。使用在线编译器,这很好用:

#include <iostream>

int randNum()
{
    unsigned int x;
    size_t y = reinterpret_cast<size_t>(&x);
    return ((y >> 16) & 0x0000FFFF);
}

int main()
{
    unsigned int x = randNum();
    std::cout << x;
    return 0;
}

在我的计算机上本地编译,但不是那么多。每次编译并运行它时,它都会将x分配给相同的内存地址。

我能理解为什么在线编译器每次都会给我一个新的内存地址,但为什么不在我的本地机器上呢?

c++ random
2个回答
0
投票

首先你需要一点背景知识。每个程序都从操作系统中获取虚假的RAM地址。它被称为虚拟地址空间,它允许进程表现得像拥有整个内存一样。该过程不必担心与其他正在运行的进程冲突。当它尝试访问内存位置时,操作系统会将虚拟地址转换为真实的“物理”地址。如果您对此感兴趣,则应查找页表。

一个进程有3个主要的内存区域。堆栈,堆和文本。堆栈保留了函数堆栈以及这些函数中定义的局部变量,例如unsigned int x。

你的randNum只是返回堆栈底部的当前位置。 (顺便说一句,这是一种安全风险)。通过简单的测试,randNum将始终返回相同的结果,因为x的地址基于堆栈。

好的,你可能想知道为什么堆栈基地总是在同一个地方开始。尽管它有一点摆动空间,但堆栈始终位于地址空间的顶部(高数字)端,例如0xBFFF0000,并且它向下“增长”,朝向低数字。当您进行右移(y >> 16)时,您实际上正在查看地址中变化最小的部分,这恰好是页面索引,可以由生活在其上的数百个变量共享的部分。同一页。

可能影响堆栈基础位置的事情:

  • 地址空间布局随机化(ASLR),一种黑客攻击对策。每次启动流程时都不一定要重新随机化。
  • 环境变量,可以来自流程外部。不一定会经常改变并依赖于机器。
  • CPU,OS,编译器......
  • 更多???

我敢打赌,在线编译器发生的事情就是每次你在不同的机器上进行编译时。每次运行时,它都在不同的机器上运行。很多人同时访问服务器,也许它对环境变量有影响?而当你在本地机器上运行时,事情相对平静。

所以我想说这是一个好主意,即使它不起作用,我希望你学到了一些有趣的东西。


4
投票

我能理解为什么在线编译器每次都会给我一个新的内存地址,但为什么不在我的本地机器上呢?

简短回答:因为标准中没有任何内容可以保证内存地址每次都相同或不同。这取决于您运行程序的位置(平台,操作系统),编译方式以及其他一千多个因素。

不要在代码中依赖这样的东西。最重要的是,如果您需要为实际项目生成随机数,请使用<random>或PCG。

© www.soinside.com 2019 - 2024. All rights reserved.