关于动态内存管理
关于动态内存管理的函数原型定义在stdlib.h
头文件中,Linux系统中该头文件所在路径为:/usr/include/
,stdlib.h
中定义的与动态内存管理相关函数的原型为:
void *malloc(size_t size);
void *calloc(size_t numElement, size_t elementSize);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
从堆中分配内存
void *malloc(size_t size)
malloc
函数通过参数指定需要分配的内存大小(单位:字节),若堆中存在足够内存则返回起始地址,否则返回NULL
,示例代码如下:#include <stdlib.h> #include <stdio.h> int main(void) { int *ptr = (int *) malloc(5 * sizeof(int)); if (!ptr) { printf("out of memory\n"); return -1; } /***** do something for ptr here *****/ free(ptr); // 释放内存 ptr = NULL; // 堆内存释放后指针变量一般置为空指针,避免造成悬空指针(dangling pointer) return 0; }
从堆中开辟的内存使用完毕必须手动释放归还给堆管理器
void *calloc(size_t numElement, size_t elementSize)
calloc
函数通过指定元素个数和元素大小分配内存,若堆中存在足够内存则返回起始地址,否则返回NULL
,示例代码如下:#include <stdlib.h> #include <stdio.h> int main(void) { int *ptr = (int *) calloc(5, sizeof(int)); if (!ptr) { printf("out of memory\n"); return -1; } /***** do something for ptr here *****/ free(ptr); ptr = NULL; return 0; }
但和
malloc
不同的是calloc
会堆开辟的内存进行零初始化,即int *ptr = (int *) calloc(5, sizeof(int));
与下述代码等价(memset函数原型定义在string.h中):int *ptr = (int *) malloc(5 * sizeof(int)); if (ptr) { memset(ptr, 0, 5 * sizeof(int)); }
void *realloc(void *ptr, size_t size)
realloc
函数作用为扩大或缩小已分配的堆内存或者NULL
,该函数接受两个参数,第一个参数指定要扩大或缩小的内存地址;第二个参数指定扩大或缩小后的内存大小,示例代码如下:#include <stdio.h> #include <stdlib.h> int main(void) { int *ptr = (int *) malloc(5 * sizeof(int)); if (!ptr) { printf("out of memory\n"); return -1; } int *tmp_ptr = (int *) realloc(ptr, 10 * sizeof(int)); if (!tmp_ptr) { printf("out of memory\n"); free(ptr); // 若不再需要ptr则需释放 ptr = NULL; return -1; } ptr = tmp_ptr; tmp_ptr = NULL; // 对于动态分配的内存一般保证只有一个引用,否则容易重复释放 /***** do something for ptr here *****/ free(ptr); ptr = NULL; return 0; }
使用
realloc
需要注意的是当内存不足返回为NULL
时,realloc
不会将参数ptr
指向的内存释放,需要人为动手释放,因此不可以写如下代码:#include <stdlib.h> int main(void) { int *ptr = (int *) malloc(5 * sizeof(int)); if (!ptr) { printf("out of memory\n"); return -1; } ptr = (int *) realloc(ptr, 10 * sizeof(int)); /*****此处若内存不足realloc返回NULL,ptr将丢失之前malloc分配的内存地址,造成内存泄漏*****/ return 0; }
释放内存
void free(void *ptr)
free
函数的作用是将从堆中分配的内存释放归还给堆,以便后续可以分配给其他的对象,该函数的参数为动态分配内存的地址。使用free
函数时要注意,参数必须为malloc
、calloc
、realloc
的返回值或NULL
,否则将产生free(): invalid pointer
运行时错误,示例代码1如下:#include <stdio.h> #include <stdlib.h> int main(void) { int a = 99; int *ptr = &a; free(ptr); // 产生运行时错误,因为ptr指向栈内存 ptr = NULL; return 0; }
示例代码2如下:
int main(void) { int *ptr = (int *) malloc(5 * sizeof(int)); ptr++; free(ptr); // 产生运行时错误,因为ptr已经不指向malloc分配内存的首地址 ptr = NULL; return 0; }