堆栈是如何初始化的?

tic*_*chy 15 c c++ linux

当进程请求内存并且操作系统向进程提供一些新页面时,内核应该初始化页面(例如,使用零),以避免显示另一个进程使用的可靠数据.当进程启动并接收一些内存时也是如此,例如堆栈段.

当我在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)
  1. 为什么它也没有设置为零?
  2. 可能是因为它被这个过程重用了吗?
  3. 如果是,那么早期使用那些3-4 kB内存的初始化代码是不是?

yan*_*yan 11

操作系统不保证零存储内存,只是你拥有它.它可能会为您提供之前使用过的内存页面(或以前从未使用过但非零值).如果应用程序存储了潜在敏感数据,则应该在free()之前将其归零.

它不会设置为零,因为这将执行不必要的工作.如果您分配20兆字节来存储纹理或几帧视频,那么为什么操作系统会将零写入所有内存,这样您就可以覆盖它们.

作为一般规则,操作系统不会执行任何他们不需要的操作.

编辑:扩展一点,当你"分配"一块内存时,所有操作系统正在做的是从一组未分配的页面重新分配内存页面(通常为4096字节的块)到你的进程.您还可以拥有共享内存,在这种情况下,操作系统会将它们分配给多个进程.这就是所有分配金额.

  • 操作系统绝对保证您不会在地址空间中看到来自其他进程的剩余数据。 (2认同)

Zan*_*ynx 5

当您通过流程获得新内存时brk(),sbrk()或者mmap()保证将其清零.

但是进程堆栈已经分配给您的进程.该alloca()函数没有获得新的堆栈空间,它只返回当前堆栈指针并将指针移动到新块的末尾.

因此,返回的内存块alloca()以前已被您的进程使用.即使你alloca()在main 之前没有函数,C库和动态加载器也一直在使用堆栈.


Jen*_*edt 4

我很确定当操作系统启动你的进程时,堆栈只是零。我认为你观察到的是另一种现象。您似乎已将程序编译为 C++。在开始之前,C++ 会执行大量代码(构造函数和类似的东西)main。所以你看到的就是你自己执行的剩余价值。

如果您将代码编译为 C(更改为“stdio.h”等),您可能会看到“污染”大大减少,甚至根本没有。特别是如果您要将程序静态链接到 C 库的简约版本。