假设使用mmap时未初始化的堆内存被初始化为零? [英] assuming uninitialized heap memory is initialized to zero when using mmap?

查看:261
本文介绍了假设使用mmap时未初始化的堆内存被初始化为零?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们知道,虽然.bss内存位置(例如未初始化的全局C变量)始终由加载程序初始化为零,但对于堆内存却并非如此.一个常见的错误是假定堆内存已初始化为零.

We know that While .bss memory locations (such as uninitialized global C variables) are always initialized to zeros by the loader, this is not true for heap memory. A common error is to assume that heap memory is initialized to zero.

但是mmap获得的已分配内存呢?我们可以通过调用mmap来请求堆内存,以使用匿名文件(需求为零的页面)映射堆中的区域,因此在这种情况下,我们可以安全地假设堆内存已初始化为零?

But what about the allocated memory obtained by mmap? We can request heap memory by calling mmap to map an arean in the heap with an anonymous file(demand-zero pages), so in this case we can safely assume that heap memory is initialized to zero?

而且,malloc实际上在内部调用mmap来请求内存以获取较大的分配,而对于较小的分配,malloc仍在内部调用sbrk/brk.对于后者,我们当然不能假定堆内存已初始化为零.

And also, malloc actually calls mmap internally to request the memory for large size of allocations, and for small size of allocations, malloc still calls sbrk/brk internally. For the latter, we certainly cannot assume that heap memory is initialized to zero.

因此,对于malloc实际上在内部调用mmap时的大型分配,我们仍然可以假设堆内存已初始化为零?我知道这仍然不是一个好习惯,我们不应该在所有情况下都将假设设为0,但我只想确保自己的理论正确无误,以使我知道对mmap的理解是正确的.

so for large size of allocations when malloc actually calls mmap internally, we can still assume that heap memory is initialized to zero? I know it is still not a good practice and we shouldn't read assume 0 under all circustanmances, but I just want to make sure my theory is correct so that I know my understanding of mmap is correct.

推荐答案

我们知道,虽然.bss内存位置(例如未初始化的全局C变量)始终由加载程序初始化为零...

We know that While .bss memory locations (such as uninitialized global C variables) are always initialized to zeros by the loader...

我不知道-可能是加载程序,可能是链接到程序中的某种语言的启动代码(例如"crt0.o"),可能是提供新页面为零"的OS/内核.确保加载程序不必费心.

I don't know that - could be the loader, could be a language's startup code linked into the program (e.g. "crt0.o"), could be the OS/kernel providing a "new pages are zeroed" guarantee where loader doesn't have to bother.

但是mmap获得的已分配内存呢?

But what about the allocated memory obtained by mmap?

mmap()的使用方式是什么?

对于POSIX;规范不包括直接用于分配内存的mmap().相反,应该为打开的内存对象"获取文件描述符. (例如,来自"posix_typed_mem_open()"),然后使用其文件描述符映射存储器对象;以及用于创建存储器对象"的功能的规范.大多只是说(非常解释)等等,定义了实现,等等,对不起,直到为时已晚,我们的规范才存在".因此,该区域是否为零没有什么可说的.

For POSIX; the spec doesn't include mmap() being used directly to allocate memory. Instead you're supposed to get a file descriptor for an opened "memory object" (e.g. from "posix_typed_mem_open()") and then map the memory object using its file descriptor; and the specs for functions to create a "memory object" mostly just say (very paraphrased) "blah blah, implementation defined, blah blah, sorry our spec didn't exist until after it was too late to matter". Because of this it has nothing to say about whether the area is zeroed or not.

对于Linux,mmap(..., MAP_ANONYMOUS)为您提供归零页面,而mmap(..., MAP_ANONYMOUS | MAP_UNINITIALIZED)可能不会.

For Linux, mmap(..., MAP_ANONYMOUS) gives you zeroed pages and mmap(..., MAP_ANONYMOUS | MAP_UNINITIALIZED) probably won't.

对于Windows,您无需使用mmap()来分配内存-您可以使用VirtualAlloc()来保证分配新内存为零.

For Windows you don't use mmap() to allocate memory - you use VirtualAlloc() instead, which guarantees the new memory is zeroed.

其他所有操作系统都可能做它想做的其他事情.

Every other OS may do whatever else it felt like.

一般而言;多任务操作系统必须担心安全性问题(例如,仍由一个进程释放的数据仍可以在由另一个进程分配后访问的仍在内存中的数据)并且出于安全原因(和方便性)而将页面填满(零).

In general; a multi-tasking OS has to worry about security problems (e.g. data still in memory that was freed by one process being accessible after its allocated by a different process) and will fill the pages (with zeros) for security reasons (and convenience).

因此,对于大型分配,当malloc实际上在内部调用mmap时,我们仍然可以假定堆内存已初始化为零?

so for large size of allocations when malloc actually calls mmap internally, we can still assume that heap memory is initialized to zero?

您可以根据自己的喜好进行假设,直到发现该假设是错误的为止.这包括malloc()在内部(在某些条件下或在任何条件下)调用mmap()的假设.例如,C库仅可以在程序的.bss中保留大量空间,并将其用于malloc(),因此malloc()绝不使用mmap()sbrk()(或VirtualAlloc()或.. ).

You can assume whatever you like until you find out that the assumption is wrong. This includes the assumption that malloc() calls mmap() internally (under some conditions or under any conditions). For example, a C library could just reserve a huge amount of space in the program's .bss and use that for malloc(), so that malloc() never uses mmap() or sbrk() (or VirtualAlloc() or ...) at all.

如果您确实知道malloc()是从某个可以确保内存中充满零的位置获取了底层内存(鉴于您可以混合使用旧内存和新内存,那么这几乎是不可能的);那么您仍然不能假设malloc()(或语言运行时环境的任何其他部分-启动代码,C库等)没有临时将内存用于某些元数据,并且仍然不能假设从malloc()分配的内存在您获取时仍为零.

If you do know that malloc() got the underlying memory from somewhere that does guarantee the memory is filled with zeros (which is almost impossible to do given that you could get a mixture of old memory and new memory); then you still can't assume that malloc() (or any other part of the language's run-time environment - startup code, C libraries, etc) didn't temporarily use the memory for some meta-data, and still can't assume that memory allocated from malloc() is still zeroed by the time you get it.

请注意,堆可能会优化calloc(),因此,如果它知道内存已经用零填充(因为它一直跟踪,并且还知道底层内存最初来自提供保证的某个位置),则不会无缘无故地用零填充内存.本质上,calloc()是有保证的malloc()". (而不是"malloc()后跟memset()").

Note that the heap may optimize calloc() so that if it knows that the memory is already filled with zeros (because it kept track, and also knows the underlying memory originally came from somewhere that provides a guarantee) it doesn't fill the memory with zeros for no reason. Essentially, calloc() is "malloc() with a guarantee" (and not "malloc() followed by memset()").

这篇关于假设使用mmap时未初始化的堆内存被初始化为零?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆