当进程请求内存并且操作系统向进程提供一些新页面时,内核应该初始化页面(例如,使用零),以避免显示另一个进程使用的可靠数据.当进程启动并接收一些内存时也是如此,例如堆栈段.
当我在Linux中执行以下代码时,结果是大部分已分配的内存确实为0,但堆栈底部大约3-4 kB(数组的最后一个元素,最高地址)包含随机数.
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int * a = (int*)alloca(sizeof(int)*2000000);
for(int i = 0; i< 2000000; ++i)
cout << a[i] << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
yan*_*yan 11
操作系统不保证零存储内存,只是你拥有它.它可能会为您提供之前使用过的内存页面(或以前从未使用过但非零值).如果应用程序存储了潜在敏感数据,则应该在free()之前将其归零.
它不会设置为零,因为这将执行不必要的工作.如果您分配20兆字节来存储纹理或几帧视频,那么为什么操作系统会将零写入所有内存,这样您就可以覆盖它们.
作为一般规则,操作系统不会执行任何他们不需要的操作.
编辑:扩展一点,当你"分配"一块内存时,所有操作系统正在做的是从一组未分配的页面重新分配内存页面(通常为4096字节的块)到你的进程.您还可以拥有共享内存,在这种情况下,操作系统会将它们分配给多个进程.这就是所有分配金额.
当您通过流程获得新内存时brk()
,sbrk()
或者mmap()
保证将其清零.
但是进程堆栈已经分配给您的进程.该alloca()
函数没有获得新的堆栈空间,它只返回当前堆栈指针并将指针移动到新块的末尾.
因此,返回的内存块alloca()
以前已被您的进程使用.即使你alloca()
在main 之前没有函数,C库和动态加载器也一直在使用堆栈.
我很确定当操作系统启动你的进程时,堆栈只是零。我认为你观察到的是另一种现象。您似乎已将程序编译为 C++。在开始之前,C++ 会执行大量代码(构造函数和类似的东西)main
。所以你看到的就是你自己执行的剩余价值。
如果您将代码编译为 C(更改为“stdio.h”等),您可能会看到“污染”大大减少,甚至根本没有。特别是如果您要将程序静态链接到 C 库的简约版本。