(十一)动态内存分配
数组的元素存储于内存中连续的位置上。当一个数组被声明时,它所需要的内存在编译时就被分配,但是你也可以使用动态内存分配在运行时为它分配内存。
malloc 和 free
C函数库提供了两个函数,malloc和free,分别用于执行动态内存分配和释放
void *malloc(size_t size); /* size为需要分配的内存字节数*/
void free(void *pointer);
调用malloc函数时,malloc从内存池中提取一块合适的内存,并向该程序返回一个指向这块内存的指针。malloc不对内存进行初始化。
当一块以前分配的内存不再使用时,程序调用free函数把它归还给内存池供以后之需。
如果操作系统无法向malloc提供更多的内存,malloc就返回一个NULL指针。因此,对每个从malloc返回的指针都进行检查,确保它并非NULL是非常重要的。
free的参数必须要么是NULL,要么是一个先前从malloc、calloc或realloc返回的值。向free传递一个NULL参数不会产生任何效果。
calloc和realloc
void *calloc(size_t num_elements, size_t element_size); /* num_elements为所需元素的数量, element_size为每个元素的字节数*/
void realloc(void *ptr, size_t new_size);
calloc在返回指向内存的指针之前把内存初始化为0。calloc的参数包括所需元素的数量和每个元素的字节数。
realloc函数用于修改一个原先已经分配的内存块的大小。使用这个函数,你可以使一块内存扩大或缩小。如果它用于扩大一个内存块,那么这块内存原先的内容依然保留,新增加的内存添加到原先内存块的后面,新内存并未以任何方法进行初始化。如果它用于缩小一个内存块,该内存块尾部的部分内存便被拿掉,剩余部分内存的原先内容依然保留。
如果原先的内存块无法改变大小,realloc将分配另一块正确大小的内存,并把原先那块内存的内容复制到新的块上。因此在使用realloc之后,应该改用realloc所返回的新指针。
如果realloc函数的第1个参数是NULL,那么它的行为就和malloc一模一样。
使用动态分配的内存
int *pi;
...
pi = malloc(100);
if(pi == NULL){
printf("Out of memory!\n");
exit(1);
}
如果内存分配成功,那么我们就拥有了一个指向100个字节的指针。在整型为4个字节的机器上,这块内存将被当作25个整形元素的数组,因为pi是一个指向整型的指针。
pi = malloc(25 * sizeof(int));
这种方法更好一些。
访问:
int *pi2, i;
...
pi2 = pi;
for(i = 0; i < 25; i+=1)
*pi2++ = 0;
or
int i;
...
for(i = 0; i < 25; i+=1)
pi[i] = 0;
常见的动态内存错误
1、对NULL指针进行解引用操作
2、对分配的内存进行操作时越过边界
3、释放并非动态分配的内存
4、试图释放一块动态分配的内存的一部分
5、一块动态内存被释放之后被继续使用