malloc如何运作?

Raj*_*Raj 11 c malloc

可能重复:
free和malloc如何在C中工作?

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

小智 41

这个问题有点不对劲.

在典型的OS中,存在虚拟存储器和物理存储器的概念.

物理内存通常存在于4kb块中,虚拟内存同样存在.

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

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

所以你仍然可以遇到虚拟内存碎片.这里,进程请求存储器块,并且在该特定进程虚拟存储器映射中,不存在可以满足请求的虚拟存储器块.

那个问题是你想到的问题.

  • 想象一下,你有一个过程.它一直在进行大量的分配和解除分配.它的虚拟内存映射是高度分散的 - 大量的分配,大量的差距.您可能会发现,当达到最大差距时,您可以达到5 MB长.然后尝试malloc 10兆字节.这将失败.在虚拟内存映射中没有任何地方可以进行有意义的10 MB分配 - 即使有足够的物理内存可用于该分配. (4认同)

daw*_*awg 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 */
Run Code Online (Sandbox Code Playgroud)

将在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 */
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

对于20字节的快速块,请考虑使用STACK.这就是它的用途.看看这篇SO帖子,看看STACK与HEAP的特征.

阅读calloc,malloc,reallocC指南,免费获取更多信息.


wkl*_*wkl 7

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

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

§7.20.3中的ISO/IEC 9899-1999 C标准:

如果分配(by calloc,,reallocmalloc)成功,则返回指针,以便可以将其指定给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到空间明确解除分配).

它不是那么明确,但段落提到"访问这样的对象的数组",而在C标准中,数组是:

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

还要注意的是后续调用calloc,realloc以及malloc不保证连续性或内存排序(与已经分配的其他内存块).

这一点也在§7.20.3中规定.

的顺序和连续调用到所分配的存储的邻接calloc,mallocrealloc功能是不确定的.


Joh*_*ski 5

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