7.6 动态内存:malloc 与 free
内存分区与为什么需要堆
程序运行时的内存大致分成几块:代码区(指令)、数据区(全局/静态变量)、栈区(stack,存放局部变量,由编译器自动分配和释放)、堆区(heap,由程序员手动分配和释放)。
栈上的局部数组在函数返回后就被释放了,所以不能把它的地址返回给调用者。另外,数组一旦声明,容量就固定了。当数组大小要在运行时才决定,或数据需要在函数返回后继续存在时,就需要在堆上动态申请内存。
malloc 与 free
malloc(size) 在堆上申请 size 个字节,返回指向这块内存的指针,失败时返回 NULL。它返回的是无类型指针 void *,需要自己转换成对应类型。用完要用 free() 归还,否则会造成内存泄漏(memory leak)。
c
int *arr = (int *) malloc(n * sizeof(int));
if (arr == NULL) {
return 1; // 申请失败
}
// ... 使用 arr ...
free(arr); // 用完释放calloc 与 realloc
calloc(n, size) 申请 n 个 size 字节的空间,并把它们全部初始化为 0;malloc 不会初始化。
c
int *arr = (int *) calloc(n, sizeof(int)); // 全部为 0realloc(ptr, size) 用于给已申请的内存重新调整大小(扩容或缩小),它会把原有数据复制到新内存,并返回新指针,失败时返回 NULL。
c
int *next = realloc(arr, new_size * sizeof(int));
if (next == NULL) {
free(arr);
return 1;
}
arr = next;下面的函数在堆上生成斐波那契数列并返回,由调用者在用完后负责 free:
c
int *generate_fibonacci(int n) {
int *arr = (int *) malloc(n * sizeof(int));
if (arr == NULL) {
return NULL;
}
arr[0] = 1;
arr[1] = 1;
for (int i = 2; i < n; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
return arr;
}使用动态内存时要格外谨慎:检查 NULL、避免越界、避免重复释放、free 之后不要再使用旧指针。
正在加载交互实验...
正在加载概念检查...
正在加载本节练习...
正在加载本节练习...