动态内存管理 malloc/free
malloc/calloc/realloc/free、内存泄漏、悬空指针、valgrind
动态内存管理 malloc/free
堆(heap)是你向操作系统申请的内存——手动申请,手动释放。用的好灵活高效,用的不好内存泄漏、悬空指针。
学完本章你将: 掌握 malloc/calloc/realloc/free、内存泄漏排查、valgrind 检测。
malloc —— 申请内存
c
#include <stdio.h>
#include <stdlib.h> // malloc, free
int main() {
// 申请 5 个 int 的空间
int *arr = (int *)malloc(5 * sizeof(int));
if (arr == NULL) {
printf("内存分配失败!\n");
return 1;
}
for (int i = 0; i < 5; i++) {
arr[i] = i * 10;
}
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); // 0 10 20 30 40
}
free(arr); // 用完了,释放!
return 0;
}
calloc —— 申请 + 清零
c
// calloc(n, size) → 分配 n 个大小为 size 的空间并清零
int *arr = (int *)calloc(5, sizeof(int));
// 等价于 malloc(5 * sizeof(int)) + 手动清零
realloc —— 调整大小
c
int *arr = (int *)malloc(3 * sizeof(int));
arr[0] = 1; arr[1] = 2; arr[2] = 3;
// 扩大到 5 个元素
arr = (int *)realloc(arr, 5 * sizeof(int));
arr[3] = 4; arr[4] = 5;
free(arr);
⚠️ realloc 可能移动数据到新地址!始终用返回值覆盖原指针,不要假设地址不变。
内存泄漏 —— 致命错误
c
// ❌ 内存泄漏
void leak() {
int *p = malloc(100);
// 忘了 free —— 函数返回后 p 消失,但内存没释放
}
// ✅ 正确做法
void noLeak() {
int *p = malloc(100);
// ... 使用 ...
free(p);
}
常见内存错误
c
// 1. 重复释放
int *p = malloc(10);
free(p);
// free(p); // ❌ 未定义行为!
// 2. 使用已释放的内存
int *p = malloc(10);
free(p);
*p = 42; // ❌ 悬空指针!
// 3. free 非 malloc 的地址
int x;
// free(&x); // ❌ 不是堆内存!
// ✅ 防御:释放后置 NULL
free(p);
p = NULL;
// ✅ 检测工具
// valgrind --leak-check=full ./program