当你在 Linux 中恶意移动内存时,根据规范,它不能保证为零。那么,您获得谁的数据呢?
你会得到"随便"。如果进程之前分配并释放了内存,则通常至少会部分填充旧内容。有时内存中会专门填充垃圾,以使错误更加明显。你不会得到的是其他一些进程的旧数据;这将是一个潜在的安全漏洞。
简单的答案:这是你的数据。(从你看到它的那一刻起)由你来做任何你想做的事情。
您的问题的性质是:以前是谁的数据?谁在那里写的?这不是一个容易回答的问题,因为跟踪数据已经丢失。检查数据本身可能会给您提示,但这只是猜测。
现在,怎么会呢?物理内存(逻辑上)按页面划分,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是自由软件的优势,研究GNU libc或MUSL libc中malloc
&free
的实现。
有几种可能发生的情况。
想象一个不断malloc()
s和free()
s的过程。
第一个malloc()
开始从操作系统获得更多内存。此内存很可能填充为 0。你使用它(在其中放一些数据)并最终再次释放它。
现在可能会发生以下情况:
-
内存位于堆的末尾,可以使用
sbrk()
释放。仅当有足够的释放量时,才会发生这种情况,因为释放在性能方面非常昂贵。堆末尾必须可用的数据量与mallopt()
选项M_TRIM_THRESHOLD
有关。 -
但是,如果内存没有立即释放,而是添加到可用内存块列表中,则以后调用
malloc()
可能会返回它(或其中的一部分)。在这种情况下,您之前放在这里的数据可以从那里读出(如果这样做有任何意义的话)。