内存泄漏
内存泄漏是指程序动态分配的内存不再使用但未被释放,导致可用内存逐渐减少。长期运行的程序(如服务器)中,内存泄漏会累积最终导致程序崩溃或系统资源耗尽。
典型内存泄漏场景
丢失指针:
void leak(void)
{
int *p = malloc(100);
p = malloc(200); /* 第一个 100 字节泄漏! */
free(p);
}
异常路径未释放:
void process(void)
{
int *data = malloc(1000);
if (some_error()) {
return; /* 泄漏!未 free(data) */
}
/* 处理 */
free(data);
}
循环中重复分配:
for (int i = 0; i < 1000; i++) {
int *p = malloc(100); /* 每次迭代分配,从不释放 */
/* 使用 p */
/* 忘记 free(p) */
}
检测内存泄漏
简单计数:
static int alloc_count = 0;
void *my_malloc(size_t size)
{
alloc_count++;
return malloc(size);
}
void my_free(void *p)
{
if (p != NULL)
alloc_count--;
free(p);
}
/* 程序结束时 alloc_count 应为 0 */
预防内存泄漏
单一出口:
void process(void)
{
int *data = malloc(1000);
int result = 0;
if (some_error()) {
result = -1;
goto cleanup; /* 统一释放 */
}
/* 处理 */
cleanup:
free(data);
return result;
}
RAII 模式:
struct Resource {
int *data;
};
struct Resource *create(void)
{
struct Resource *r = malloc(sizeof(struct Resource));
r->data = malloc(1000);
return r;
}
void destroy(struct Resource *r)
{
if (r != NULL) {
free(r->data);
free(r);
}
}
最佳实践
malloc和free配对- 异常路径也要释放内存
- 使用工具(Valgrind、AddressSanitizer)检测
- 设计清晰的资源生命周期
- 考虑使用内存池管理复杂对象