可能重复:
free和malloc如何在C中工作?
考虑一种情况,我必须通过malloc分配大约20个字节的内存.对于malloc()的函数调用是否成功,20个字节是否应该在内存中连续可用或者是否可以分散?例如,在上面的例子中,如果有4个或5个块,每个10个字节,malloc会工作吗?或者这是特定于操作系统还是特定于编译器?
小智 41
这个问题有点不对劲.
在典型的OS中,存在虚拟存储器和物理存储器的概念.
物理内存通常存在于4kb块中,虚拟内存同样存在.
每个进程都有虚拟内存 - 对于每个进程,操作系统都会显示完全可寻址的内存范围.所以在32位机器上,每个进程"认为"它有4 GB的内存.
实际上,操作系统在幕后忙于将虚拟内存分配映射到实际的物理内存块上.因此,例如,400kb虚拟内存分配被映射到100个物理块.这些物理块不需要是有条件的(并且几乎从来都不是 - 没有什么能阻止它发生,但是在进行任何工作的机器上,这是非常不可能的)但是虚拟内存分配确实需要是有意义的.
所以你仍然可以遇到虚拟内存碎片.这里,进程请求存储器块,并且在该特定进程虚拟存储器映射中,不存在可以满足请求的虚拟存储器块.
那个问题是你想到的问题.
调用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,realloc的C指南,免费获取更多信息.
标准malloc在C标准中定义为分配一个连续的内存块(至少它对你来说是这样) - 如果分配失败,它将返回一个空指针.
在较低级别,操作系统将执行类似kotlinski或Blank Xavier在各自答案中所描述的内容.
从§7.20.3中的ISO/IEC 9899-1999 C标准:
如果分配(by
calloc,,realloc或malloc)成功,则返回指针,以便可以将其指定给指向任何类型对象的指针,然后用于在分配的空间中访问此类对象或此类对象的数组(直到空间明确解除分配).
它不是那么明确,但段落提到"访问这样的对象的数组",而在C标准中,数组是:
数组类型描述了具有特定成员对象类型的连续分配的非空对象集,称为元素类型.(来自§6.2.5)
还要注意的是后续调用calloc,realloc以及malloc不保证连续性或内存排序(与已经分配的其他内存块).
这一点也在§7.20.3中规定.
的顺序和连续调用到所分配的存储的邻接
calloc,malloc和realloc功能是不确定的.
这是特定于平台的.对于您的眼睛,在软件级别,它将始终显示为malloc:ed 20连续字节.但是在某些平台上,例如使用分页内存,这些字节在涉及实际硬件时并不需要连续 - 它只会出现.