C语言 malloc 是如何工作的?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3954188/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How malloc works?
提问by Raj
Possible Duplicate:
How do free and malloc work in C?
可能的重复:
free 和 malloc 如何在 C 中工作?
Consider a scenario where i have to allocate some 20 bytes of memory through malloc. For the function call to malloc() to be successful, should the 20 bytes be available contiguously in memory or can it be scattered? For eg, in the above case, if there are 4 or 5 chunks of 10 bytes each, will malloc work? Or is this OS specific or compiler-specific?
考虑一个场景,我必须通过 malloc 分配大约 20 字节的内存。为了成功调用 malloc() 的函数,这 20 个字节应该在内存中连续可用还是可以分散?例如,在上述情况下,如果有 4 或 5 个 10 字节的块,malloc 会起作用吗?或者这是特定于操作系统还是特定于编译器?
回答by
The question is kind of wrong.
这个问题有点错误。
In a typical OS, there exists the concepts of virtual memory and physical memory.
在典型的操作系统中,存在虚拟内存和物理内存的概念。
Physical memory exists typically in 4kb blocks, virtual memory likewise.
物理内存通常以 4kb 块的形式存在,虚拟内存也是如此。
Each process has virtual memory - to each process the OS presents what appears to be the fully addressable memory range. So on a 32 bit machine, each process 'thinks' it has 4 GB of contigious memory.
每个进程都有虚拟内存 - 操作系统向每个进程提供似乎是完全可寻址的内存范围。所以在 32 位机器上,每个进程“认为”它有 4 GB 的连续内存。
In reality, the OS, behind the scenes, is busy mapping virtual memory allocations onto real blocks of physical memory. So a, say, 400kb virtual memory allocation, is mapped onto 100 physical blocks. Those physical blocks do not need to be contigious (and almost never are - nothing stops it from happening, but on a machine doing any kind of work, it's highly improbable) but the virtual memory allocation doesneed to be contigious.
实际上,操作系统在幕后忙于将虚拟内存分配映射到实际的物理内存块。因此,比如说,400kb 的虚拟内存分配被映射到 100 个物理块上。这些物理块不需要是连续的(几乎从来没有 - 没有什么可以阻止它发生,但在一台机器上做任何类型的工作,这是极不可能的)但虚拟内存分配确实需要是连续的。
So you can still run into virtual memory fragmentation. Here, a process requests a block of memory and there isn't, in that particular processes virtual memory map, a block of contigious virtual memory such that the request can be satisfied.
所以你仍然可能遇到虚拟内存碎片。在这里,一个进程请求一块内存,而在那个特定的进程虚拟内存映射中,没有一块连续的虚拟内存可以满足请求。
That problem is the problem you're thinking of.
那个问题就是你正在考虑的问题。
回答by dawg
The call to mallocwill either succeed in returning a logically contiguous blockof memory from your program's HEAP memory space equal to the size requested or it will fail with a NULL pointer. "Logically contiguous" means that with a mallocof this type:
调用malloc将成功从程序的 HEAP 内存空间中返回逻辑上连续的内存块,该内存块等于请求的大小,或者它将失败并返回 NULL 指针。“逻辑上连续”意味着使用malloc这种类型的 a:
int *ip; /* Nothing yet allocated (other than the size of a pointer... */
int ar[100]; /* 100 ints on the STACK */
ip = (int *)malloc(sizeof ar); /* if that succeeds, 100 ints on the HEAP */
will allocate space for 100 ints on your OS on the HEAP and return either NULL or the pointer. Separately, the array aris allocated on the STACK. Each array will be laid out with all the ints logically next to each other, at least as far your program knows. If they were not next to each other, you would not be able to address these blocks as arrays with the array[offset]notation or with pointer arithmetic.
将在 HEAP 上的操作系统上为 100 个整数分配空间并返回 NULL 或指针。单独地,数组ar在堆栈上分配。每个数组都将与所有整数在逻辑上彼此相邻排列,至少就您的程序所知。如果它们不相邻,您将无法使用array[offset]符号或指针算法将这些块作为数组进行寻址。
You can then access either STACK or HEAP blocks of memory with an array access or pointer access interchangeably like this:
然后,您可以使用数组访问或指针访问交替访问堆栈或堆内存块,如下所示:
ip[2]=22; /* the second element of ip[] is '22' */
*(ar+33)=3333; /* the 33 element of ar is '3333' */
i=*(ip+2); /* assign using pointers */
j=ar[33]; /* assign using array offsets */
If the memory block returned by mallocwere not logically contiguous to your program, you would not be able to access the block with pointer arithmetic or array subscripting.
如果由 返回的内存块malloc在逻辑上与您的程序不连续,您将无法使用指针算术或数组下标访问该块。
Behind the scenes, your OS may move other blocks of memory that are moveable, use virtual memory, swap other items to virtual memory, etc, in order to increase the HEAP allocated to your program. Malloc can either be a very fast or very expensive call -- depending what else is going on on that system and the HEAP space allocated to your program.
在幕后,您的操作系统可能会移动其他可移动的内存块、使用虚拟内存、将其他项目交换到虚拟内存等,以增加分配给您的程序的 HEAP。Malloc 可以是非常快的调用,也可以是非常昂贵的调用——取决于该系统上正在发生的其他事情以及分配给您的程序的 HEAP 空间。
HEAP memory (that part accessed with dynamic system calls in C) is potentially subject to fragmentation. Say you allocated the number of 20 byte blocks where memory becomes scarce. Now image that you free every other block of those blocks. You will have highly fragmented memory since blocks allocated with malloccannot be moved if it effects the pointer that the program uses to access the block. (It can be moved transparently, but don't count on that being efficient.)
HEAP 内存(用 C 中的动态系统调用访问的那部分)可能会受到碎片化的影响。假设您分配了内存不足的 20 字节块的数量。现在想象一下,您释放了这些块的所有其他块。您将拥有高度碎片化的内存,因为malloc如果它影响程序用于访问块的指针,则分配的块将无法移动。(它可以透明地移动,但不要指望它是有效的。)
If you are making many calls for HEAP memory, consider changing your logic to use reallocto grow and shrink the memory as needed. A big 'gotcha' with realloc is the pointer to your existing data may change, so only use 1 pointer to it. Realloc allows the OS to move the data as needed to have a better fit with what is available on the HEAP. You will (mostly) avoid the potential for memory fragmentation that way.
如果您多次调用 HEAP 内存,请考虑更改逻辑以用于realloc根据需要增加和缩小内存。realloc 的一个大“问题”是指向您现有数据的指针可能会更改,因此只使用 1 个指向它的指针。Realloc 允许操作系统根据需要移动数据以更好地适应 HEAP 上的可用内容。您将(主要)以这种方式避免内存碎片的可能性。
For quick blocks of 20 bytes, consider using the STACK. That is what it is for. Look at this SO postto see characteristics of STACK vs HEAP.
对于 20 字节的快速块,请考虑使用堆栈。这就是它的用途。查看此 SO 帖子以了解堆栈与堆的特征。
Read the C Guide of calloc, malloc, realloc, freefor more info.
阅读calloc、malloc、realloc的C 指南,免费获取更多信息。
回答by wkl
Standard mallocis defined in the C standard to allocate a contiguous block of memory (at least it appears so to you) - it will return a null pointer if the allocation fails.
标准malloc在 C 标准中定义为分配一个连续的内存块(至少在你看来是这样) - 如果分配失败,它将返回一个空指针。
At a lower level, the OS will be doing something like what kotlinskior Blank Xavierhave described in their respective answers.
在较低级别,操作系统将执行类似于kotlinski或Blank Xavier在其各自答案中所描述的操作。
From §7.20.3of the ISO/IEC 9899-1999 C Standard:
从§7.20.3中的ISO / IEC 9899-1999 C标准:
The pointer returned if the allocation (by
calloc,realloc, ormalloc) succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated(until the space is explicitly deallocated).
如果分配(by
calloc、realloc或malloc)成功,则返回的指针经过适当对齐,以便可以将其分配给指向任何类型对象的指针,然后用于访问分配的空间中的此类对象或此类对象的数组(直到空间被显式释放)。
It is not that explicit, but the paragraph mentions 'accessing an array of such objects', and in the C standard, arrays are:
这不是那么明确,但该段落提到“访问此类对象的数组”,并且在 C 标准中,数组是:
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. (from §6.2.5)
数组类型描述了具有特定成员对象类型的连续分配的非空对象集,称为元素类型。(来自§6.2.5)
Also note that subsequent calls to calloc, realloc, and mallocdo not guarantee contiguity or ordering of memory (with other memory blocks already allocated).
另请注意,对calloc、realloc和 的后续调用malloc不保证内存的连续性或排序(已分配其他内存块)。
This point is also specified in §7.20.3.
这一点也在§7.20.3 中指定。
The order and contiguity of storage allocated by successive calls to the
calloc,malloc, andreallocfunctions is unspecified.
的顺序和连续调用到所分配的存储的邻接
calloc,malloc和realloc功能是不确定的。
回答by Johan Kotlinski
This is platform specific. To your eyes, on the software level, it will always be presented as you malloc:ed 20 contiguous bytes. But on some platforms, e.g. with paged memory, these bytes do not really need to be contiguous when it comes down to the actual hardware - it will just appear so.
这是特定于平台的。在你看来,在软件层面,它总是会在你 malloc:ed 20 个连续字节时呈现。但是在某些平台上,例如使用分页内存,当涉及到实际硬件时,这些字节实际上并不需要是连续的——它只是看起来如此。
回答by Ziffusion
OS specific.
操作系统特定。
If it's a system that has virtual memory, malloc is just going to allocate another page of VM and add it to its heap, and then hand you the memory you need. The chunk of memory within the page has to be contiguous though. Interestingly, if your demand is bigger than the page size, the memory doesn't have to be contiguous in physical memory. Two pages of VM can be made contiguous, regardless of where they are located in physical memory.
如果它是一个具有虚拟内存的系统,malloc 只会分配 VM 的另一页并将其添加到其堆中,然后将所需的内存交给您。页面内的内存块必须是连续的。有趣的是,如果您的需求大于页面大小,则内存不必在物理内存中连续。可以使 VM 的两页连续,而不管它们位于物理内存中的什么位置。
If it's a system that does not have VM, then yes, all the memory you request needs to be contiguous in physical memory.
如果它是一个没有 VM 的系统,那么是的,您请求的所有内存都需要在物理内存中是连续的。
回答by BrokenGlass
The memory has to be continuous - what you are mentioning is generally referred to as memory fragmentation, and is a real problem for applications acquiring and freeing memory very often.
内存必须是连续的——你所提到的通常被称为内存碎片,对于经常获取和释放内存的应用程序来说,这是一个真正的问题。
回答by David R Tribble
From the ISO C99standard:
来自ISO C99标准:
7.20.3 Memory management functions
The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some
nonzero value, except that the returned pointer shall not be used to access an object.
7.20.3 内存管理功能
对 calloc、malloc 和 realloc 函数的连续调用所分配的存储的顺序和连续性未指定。如果分配成功,则返回的指针经过适当对齐,以便可以将其分配给指向任何类型对象的指针,然后用于访问分配的空间中的此类对象或此类对象的数组(直到显式释放空间) . 已分配对象的生命周期从分配到释放。每个这样的分配应产生一个指向与任何其他对象不相交的对象的指针。返回的指针指向分配空间的开始(最低字节地址)。如果无法分配空间,则返回空指针。如果请求的空间大小为零,则行为是实现定义的:返回空指针,
7.20.3.3 The malloc function
The malloc function allocates space for an object whose size is specified by sizeand
whose value is indeterminate.
7.20.3.3 malloc 函数
malloc 函数为大小由 指定size且值不确定的对象分配空间。
So in other words, if you ask for space for a 20-byte object, you get enough space in which to fit a 20-byte object.
所以换句话说,如果你为一个 20 字节的对象请求空间,你就会得到足够的空间来容纳一个 20 字节的对象。
回答by Ben Strasser
Most likely it will not work. malloc can not rearrange already allocated memory so it can't make a continuous free block of 20 byte. It can only ask the OS to get another page of memory from, of which it can chop of 20 bytes + header.
很可能它不会工作。malloc 无法重新排列已分配的内存,因此它无法生成 20 字节的连续空闲块。它只能要求操作系统从中获取另一页内存,其中它可以切割 20 个字节 + 标头。

