当您在 linux 中 malloc 内存时,不能保证根据规范将其归零。那么你会得到谁的数据呢?
4 回答
你得到“随便”。如果该进程先前已分配和释放内存,通常它至少会部分填充旧的东西。有时内存会被垃圾填满,以使错误更加明显。你不会得到的是一些其他进程的旧数据;那将是一个潜在的安全漏洞。
简单的回答:这是您的数据。(从你看到它的那一刻起)你可以用它做任何你想做的事情。
你的问题的本质是:之前是谁的数据?谁在那里写的?这不是一个容易回答的问题,因为跟踪数据已经丢失。检查数据本身可能会给您一些提示,但这只是猜测。
现在,怎么来了?物理内存(逻辑上)按页面划分,MMU(内存管理单元 - CPU 的一部分)按需分配给虚拟内存中的进程。然后进程可以用数据填充页面。当进程死亡时,它的内存页面被回收为不再使用,并且当它们需要内存页面存在于虚拟内存中时可以自由地提供给其他进程。但是这些页面之前并没有被擦干净——它们是按原样给出的。因此,新进程将看到前任所有者设置的所有位。但之前主人本身的所有痕迹都已经消失了……
请注意,我还没有提到malloc()
。这是因为所谓的内存分配器根本不参与这个过程。malloc()
只是您的私有,进程中的东西,不涉及物理级别的内存页面跟踪。请记住,所有进程都有整个可用地址空间(整个 4GB 及以上)可供使用。即使机器中没有那么多物理内存。这就是为什么它被称为虚拟。即使你的机器上有 32GB 内存,产生 10 个进程,你也只是用汇总的虚拟内存检查了你的物理内存。但回到malloc()
:你的进程需要一种方法来记住它实际使用了哪些内存部分,哪些没有。当然,如果你的需求是静态的,你可以说这个结构在这里,那个结构在那里。但是当您按需创建内存结构时?这就是内存分配器库函数(通常已经在标准 C 库中)发挥作用的地方。它为您跟踪已使用的内存块,并可以为您提供指向某些未使用内存部分的指针。但是这个(虚拟)内存已经存在了。它可能没有附加物理页面,但是当您实际尝试访问它时它会。
malloc()
还可以将您指向您的进程已经使用的内存区域,并通过调用将其标记为不再使用free()
。那么它仍然是你的数据。如果您正在写入该区域,这就是您设置的位。
我们做了一个完整的回合。
malloc(3)和都free
与虚拟内存有关,它们使用mmap(2)和munmap(2)
(也许还有sbrk
)系统调用。
但是使用这些系统调用有点昂贵。
因此,malloc
尽量重用以前的 free
-d 内存区域(以避免产生过多的mmap
&munumap
系统调用),并且该内存包含任意数据(称为垃圾)。同样,free
不要向内核释放内存(使用munmap
),而只需记住您拥有的内存free
-d 稍后可重用(由malloc
)它是您自己的应用程序以前使用(并填充)的数据。
利用 Linux 是免费软件的优势,研究malloc
& free
在GNU libc或MUSL libc中的实现
有几种选择可能会发生什么。
想象一个不断malloc()
s 和free()
s 的过程。
第一个malloc()
s 开始从操作系统获取更多内存。该内存很可能被 0 填充。您使用它(将一些数据放入其中)并最终再次释放它。
现在可能发生以下情况:
要么内存位于堆的末尾,并且可以使用
sbrk()
. 仅当有足够的释放时才会发生这种情况,因为释放在性能方面非常昂贵。堆末尾必须空闲的数据量与mallopt()
选项有关M_TRIM_THRESHOLD
。但是,如果内存没有立即释放,而是添加到空闲内存块列表中,则它(或其中的一部分)可能会在稍后调用
malloc()
. 在这种情况下,您之前放在这里的数据可以从那里读出(如果有这样做的话)。