malloc像calloc一样工作 MAP_UNINITIALIZED从Linux 2.6.33开始

问题描述

运行malloc时,它将生成内存块,该内存块未设置任何值,并且包含垃圾值。当calloc运行时,发生了一些事件,例如malloc函数,但有一个区别。当calloc生成新块时,它将在该块中设置0(零)。

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

根据此信息,前五个值必须包含垃圾值(实际上应该看起来像随机数据),后五个值必须为零。但是,当此代码在Windows中运行时,没有问题,但是当此代码在Linux中运行时,不会发生这种情况。我以为它依赖于ASLR或DEP保护,因此我关闭了ASLR,并使用旧的Linux系统进行DEP保护,但是结果是相同的。最后,我认为这可能取决于C Standard,并且在编译Code时更改了C Standard,但结果没有不同。我问这是什么原因。

解决方法

malloc不会用零填充数据(如您预期的那样)。但是不能保证垃圾数据不为零。所以没关系,如果您分配内存,并且有时或在某些情况下看到所有字段都为零。我假设如果大小更大,或者如果分配,填充,释放,再分配,那么您将在“分配的”内存中看到“更多随机”数据。但是使用calloc,即使经过这样的操作,您仍然会看到内存为零。

,

malloc的行为是,它返回未初始化的内存。从未初始化的内存读取是未定义的行为,这意味着可能会发生任何事情。并且一个足够聪明的编译器可以检测到您正在从未初始化的内存中进行读取,甚至可以优化读取操作并将其替换为恒定值,甚至终止程序。

话虽这么说,由于安全问题,您正在读取零而不是存储在该部分内存中的任何东西的剩余值。几年前它实际上就是那样。但是后来人们意识到,这可能会泄露密钥或其他机密,因此Linux(和* BSD)内核的行为已更改,因此memory pages在首次映射到进程时被清零。对于Linux,此行为已在Linux-2.6.33中引入。 mmap syscall(这是malloc / calloc分配器在内部与内核进行通信的方式)获得了一个新的标志:

MAP_UNINITIALIZED(从Linux 2.6.33开始)

不要清除匿名页面。该标志旨在提高嵌入式设备的性能。仅当内核配置了CONFIG_MMAP_ALLOW_UNINITIALIZED选项时,才会使用此标志。由于存在安全隐患,因此通常仅在嵌入式设备(即完全控制用户内存内容的设备)上启用该选项。