动态内存管理
在编写程序时,常常 不知道要处理多少数据,或者难以预料要处理的数据变动是否会大。所以,要达到有效的资源运作,必须在运行时动态的分配所需要的内存,并尽早释放不需要的内存。这就是动态内存管理的原理。
标准链接库提供下面四个函数,进行内存管理:
分配新的内存区域:
malloc() calloc()
调整以前分配的内存区域
realloc()
释放以前分配的内存区域
free()
这些函数都在stdlib.h头文件综合声明。
malloc和calloc的参数不一样,
void *malloc(size_t size);
malloc()函数分配连续的内存区域,体积不小于size字节。程序通过malloc()获得内存区域,但其内容尚未确定。
void *calloc(size_t count, size_t size);
calloc()函数分配不少于count*size的内存空间。换句话说,上述语句分配的空间很大,足以保存一个数组,数组包含count个元素,每个元素占用size字节。而且calloc()会把内存中每个自己都初始化为0。
两个函数都返回void指针,返回的指针值是“分配的内存区域中”第一个字节的地址。如果无法分配内存,则返回空指针。
如果内存分配成功,就会得到“指向内存区域开端”的指针。“开端”指的是此指针的值等于内存区域的最低字节地址。分配的内存区域会被对齐,任何对象类型都可以存储在该地址。
分配的内存区域会一直为程序所保留,除非显式的调用free()或realloc()释放它。程序中连续调用malloc()、calloc()或realloc()函数,所分配的内存按照何种方式安排,并没有定义。
当不再需要动态分配的内存时,应该将它归还给操作系统,可以调用free()函数。或者,可以通过调用realloc()函数来增加或减少所分配的内存区域的空间大小。函数原型如下:
void free(void *ptr);
free()函数释放动态分配的内存区域,开始地址是ptr。ptr的值可以是空指针,调用此函数时传入空指针,则函数不起任何作用。
void *realloc(void *ptr, size_t size);
realloc()函数释放ptr所指的内存区域,并分配一个大小为size字节的内存区域,返回此地址。新的内存区域可以和旧的内存区域一样,开始于相同的地址。
realloc()也会保留原始内存内容(只保留两者其中比较小的空间大小)。如果新的内存区域没有从原始区域的地址开始,那么realloc()就会将原始的内容复制到新的内存区域。如果新的内存区域比较大,那么多出来的部分的值是没有定义的。
可以把空指针当做ptr自变量传给realloc()。这样做的话,realloc()就类似于malloc(),并且准备一个新的内存区域。
传入free()和realloc()的指针自变量(如果不是空指针)必须是“尚未被释放”的“动态分配内存区域”的起始地址。换句话说,你传给这两个函数的参数如果不是空指针就是之前malloc()、calloc()、realloc()的返回结果。如果是被的值或者是已经释放过的内存地址,程序的行为时没有定义的。
这些内存管理函数会在内部做记录,追踪每一个分配内存区域大小。这就是为什么free()和realloc()函数的参数都只需要地址,不需要区域大小的缘故。