malloc如何运作?

时间:2010-10-17 16:46:09

标签: c malloc

  

可能重复:
  How do free and malloc work in C?

考虑一个场景,我必须通过malloc分配大约20个字节的内存。对于malloc()的函数调用是否成功,20个字节是否应该在内存中连续可用或者是否可以分散?例如,在上面的例子中,如果有4个或5个块,每个10个字节,malloc会工作吗?或者这个操作系统是特定的还是特定于编译器的?

8 个答案:

答案 0 :(得分:41)

这个问题有点不对。

在典型的操作系统中,存在虚拟内存和物理内存的概念。

物理内存通常存在于4kb块中,虚拟内存也是如此。

每个进程都有虚拟内存 - 对于每个进程,操作系统都会显示完全可寻址的内存范围。因此,在32位机器上,每个进程“认为”它具有4 GB的内存。

实际上,操作系统在幕后忙于将虚拟内存分配映射到实际的物理内存块上。因此,例如,400kb虚拟内存分配被映射到100个物理块。这些物理块不需要是有条件的(并且几乎从来都不是 - 没有什么能阻止它发生,但是在一台机器上做任何工作,这是非常不可能的)但是虚拟内存分配 需要是有条不紊的。

所以你仍然可以遇到虚拟内存碎片。这里,进程请求一块内存,并且在该特定进程虚拟内存映射中没有一个可以满足请求的虚拟内存块,以便满足该请求。

这个问题是你想到的问题。

答案 1 :(得分:9)

malloc的调用将成功从程序的HEAP内存空间返回逻辑上连续的块内存,该内存空间等于请求的大小,否则将失败并返回NULL指针。 “逻辑上连续”表示使用此类型的malloc

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 */

将在HEAP上为您的操作系统分配100个整数的空间,并返回NULL或指针。另外,数组ar在STACK上分配。每个数组都将在逻辑上彼此相邻的所有整数布局,至少在程序知道的范围内。如果它们不是彼此相邻,则无法将这些块作为具有array[offset]表示法的数组或使用指针算法来处理。

然后您可以使用数组访问或指针访问来访问STACK或HEAP内存块,如下所示:

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 */

如果malloc返回的内存块在逻辑上与您的程序不连续,则无法使用指针算法或数组下标访问该块。

在幕后,您的操作系统可能会移动可移动的其他内存块,使用虚拟内存,将其他项目交换到虚拟内存等,以增加分配给您的程序的HEAP。 Malloc可以是一个非常快速或非常昂贵的调用 - 取决于该系统上正在发生的其他事件以及分配给您的程序的HEAP空间。

HEAP内存(使用C语言中的动态系统调用访问的部分)可能会出现碎片。假设您分配了内存稀缺的20字节块的数量。现在,您可以释放这些块的每个其他块的图像。由于分配了malloc的块如果影响程序用于访问块的指针,则无法移动块,因此会有高度碎片化的内存。 (它可以透明地移动,但不要指望它是有效的。)

如果要对HEAP内存进行多次调用,请考虑更改逻辑以使用realloc根据需要增大和缩小内存。使用realloc的一个重要问题是指向现有数据的指针可能会发生变化,所以只能使用指向它的1指针。 Realloc允许操作系统根据需要移动数据,以便更好地适应HEAP上可用的数据。你(大多数时候)会以这种方式避免内存碎片的可能性。

对于20字节的快速块,请考虑使用STACK。这就是它的用途。查看this SO post以查看STACK与HEAP的特征。

阅读C Guide of calloc, malloc, realloc, free了解详情。

答案 2 :(得分:7)

标准malloc在C标准中定义为分配连续的内存块(至少对你来说是这样) - 如果分配失败,它将返回空指针。

在较低级别,操作系统会执行kotlinskiBlank Xavier在各自答案中所描述的内容。

§7.20.3 ISO / IEC 9899-1999 C标准

  

如果分配(callocreallocmalloc)成功,则返回指针,以便可以将其分配给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到显式释放该空格)。

这不是那么明确,但该段提到“访问这类对象的数组”,而在C标准中,数组是:

  

数组类型描述了具有特定成员对象类型的连续分配的非空对象集,称为元素类型。 (来自§6.2.5

另请注意,对callocreallocmalloc的后续调用不保证内存的连续性或排序(已分配其他内存块)。

此点也在§7.20.3中指定。

  

通过连续调用callocmallocrealloc函数分配的存储的顺序和连续性未指定。

答案 3 :(得分:5)

这是特定于平台的。对于您的眼睛,在软件级别,它将始终显示为malloc:ed 20连续字节。但在某些平台上,例如对于分页内存,当这些字节归结为实际硬件时,它们实际上并不需要连续 - 它只会出现。

答案 4 :(得分:2)

内存必须是连续的 - 你提到的内容通常被称为memory fragmentation,并且是应用程序获取和释放内存的真正问题。

答案 5 :(得分:2)

特定操作系统。

如果它是一个具有虚拟内存的系统,malloc只是要分配另一个VM页面并将其添加到其堆中,然后将所需的内存交给你。然而,页面中的内存块必须是连续的。有趣的是,如果您的需求大于页面大小,则内存不必在物理内存中连续。无论物理存储器位于何处,都可以使两页VM连续。

如果它是一个没有VM的系统,那么是的,你请求的所有内存都需要在物理内存中连续。

答案 6 :(得分:1)

来自 ISO C99 标准:

7.20.3内存管理功能
未指定通过连续调用calloc,malloc和realloc函数分配的存储的顺序和连续性。如果分配成功,则返回的指针被适当地对齐,以便可以将其指定给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到空间被显式释放) 。分配对象的生命周期从分配延伸到解除分配。每个这样的分配都应该产生一个指向与任何其他对象不相交的对象的指针。返回的指针指向分配空间的开始(最低字节地址)。如果无法分配空间,则返回空指针。如果请求的空间大小为零,则行为是实现定义的:返回空指针,或者行为就像大小是一些 非零值,但返回的指针不得用于访问对象。

7.20.3.3 malloc功能
malloc函数为大小由size指定的对象分配空间 其价值是不确定的。

换句话说,如果你要求20字节对象的空间,你就可以获得足够的空间来容纳20字节的对象。

答案 7 :(得分:-1)

很可能它不起作用。 malloc无法重新排列已分配的内存,因此无法生成20字节的连续空闲块。它只能要求操作系统从其中获取另一页内存,其中包含20个字节+标题。