内存泄漏是C语言编程中最常见的问题之一,掌握内存泄漏的防范技巧对于编写稳定、高效的程序至关重要。东巴文(db-w.cn) 将带你深入理解内存泄漏的原因与防范方法。
💡 东巴文观点:内存泄漏是程序的隐形杀手,它会在不知不觉中耗尽系统资源,导致程序崩溃。正确的内存管理是程序稳定运行的基础。
#include <stdio.h>
#include <stdlib.h>
void memoryLeakDefinition() {
printf("=== 东巴文内存泄漏的定义 ===\n\n");
printf("内存泄漏:\n");
printf(" 程序在运行过程中动态分配了内存,\n");
printf(" 但在使用完毕后没有释放,\n");
printf(" 导致这部分内存无法被再次使用。\n\n");
printf("内存泄漏的危害:\n");
printf(" 1. 逐渐耗尽系统内存\n");
printf(" 2. 程序运行速度变慢\n");
printf(" 3. 最终导致程序崩溃\n");
printf(" 4. 影响系统稳定性\n");
}
int main() {
memoryLeakDefinition();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void memoryLeakExample() {
printf("=== 东巴文内存泄漏示例 ===\n\n");
// ❌ 内存泄漏:忘记释放
int *ptr = (int *)malloc(sizeof(int));
*ptr = 100;
printf("ptr = %d\n", *ptr);
// 忘记 free(ptr);
printf("\n这是一个内存泄漏的例子\n");
printf("内存已分配但未释放\n");
}
int main() {
memoryLeakExample();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void forgetToFree() {
printf("=== 东巴文忘记释放内存 ===\n\n");
// ❌ 错误:忘记释放
int *ptr = (int *)malloc(sizeof(int));
if (ptr != NULL) {
*ptr = 100;
printf("ptr = %d\n", *ptr);
// 忘记 free(ptr);
}
printf("内存泄漏:忘记释放\n");
}
int main() {
forgetToFree();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void pointerLost() {
printf("=== 东巴文指针丢失 ===\n\n");
// ❌ 错误:指针丢失
int *ptr = (int *)malloc(sizeof(int));
*ptr = 100;
printf("ptr = %d\n", *ptr);
// 指针重新赋值,原内存丢失
ptr = (int *)malloc(sizeof(int));
*ptr = 200;
printf("ptr = %d\n", *ptr);
// 忘记 free(ptr);
printf("内存泄漏:指针丢失\n");
}
int main() {
pointerLost();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void repeatedAllocation() {
printf("=== 东巴文重复分配 ===\n\n");
// ❌ 错误:重复分配
int *ptr = (int *)malloc(sizeof(int));
*ptr = 100;
printf("ptr = %d\n", *ptr);
// 重复分配,原内存丢失
ptr = (int *)malloc(sizeof(int));
*ptr = 200;
printf("ptr = %d\n", *ptr);
// 忘记 free(ptr);
printf("内存泄漏:重复分配\n");
}
int main() {
repeatedAllocation();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void abnormalPathLeak(int flag) {
printf("=== 东巴文异常路径未释放 ===\n\n");
int *ptr = (int *)malloc(sizeof(int));
if (ptr == NULL) {
return; // 提前返回,未释放
}
*ptr = 100;
if (flag) {
printf("flag为真,提前返回\n");
return; // 提前返回,未释放
}
printf("ptr = %d\n", *ptr);
free(ptr);
}
int main() {
abnormalPathLeak(1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void nestedAllocationLeak() {
printf("=== 东巴文嵌套分配未释放 ===\n\n");
int **matrix = (int **)malloc(3 * sizeof(int *));
if (matrix == NULL) {
return;
}
for (int i = 0; i < 3; i++) {
matrix[i] = (int *)malloc(4 * sizeof(int));
if (matrix[i] == NULL) {
// ❌ 错误:前面分配的内存未释放
return;
}
}
// 使用...
// 释放
for (int i = 0; i < 3; i++) {
free(matrix[i]);
}
free(matrix);
}
int main() {
nestedAllocationLeak();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void freeInTime() {
printf("=== 东巴文及时释放内存 ===\n\n");
// ✅ 正确:及时释放
int *ptr = (int *)malloc(sizeof(int));
if (ptr != NULL) {
*ptr = 100;
printf("ptr = %d\n", *ptr);
free(ptr);
ptr = NULL;
}
printf("内存已正确释放\n");
}
int main() {
freeInTime();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void useGotoFree(int flag) {
printf("=== 东巴文使用goto统一释放 ===\n\n");
int *ptr1 = (int *)malloc(sizeof(int));
int *ptr2 = (int *)malloc(sizeof(int));
int *ptr3 = (int *)malloc(sizeof(int));
if (ptr1 == NULL || ptr2 == NULL || ptr3 == NULL) {
goto cleanup;
}
*ptr1 = 100;
*ptr2 = 200;
*ptr3 = 300;
if (flag) {
printf("flag为真,提前退出\n");
goto cleanup;
}
printf("ptr1 = %d\n", *ptr1);
printf("ptr2 = %d\n", *ptr2);
printf("ptr3 = %d\n", *ptr3);
cleanup:
if (ptr1 != NULL) free(ptr1);
if (ptr2 != NULL) free(ptr2);
if (ptr3 != NULL) free(ptr3);
printf("内存已统一释放\n");
}
int main() {
useGotoFree(1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void useDoWhileFree(int flag) {
printf("=== 东巴文使用do-while(0)统一释放 ===\n\n");
int *ptr1 = (int *)malloc(sizeof(int));
int *ptr2 = (int *)malloc(sizeof(int));
int *ptr3 = (int *)malloc(sizeof(int));
do {
if (ptr1 == NULL || ptr2 == NULL || ptr3 == NULL) {
break;
}
*ptr1 = 100;
*ptr2 = 200;
*ptr3 = 300;
if (flag) {
printf("flag为真,提前退出\n");
break;
}
printf("ptr1 = %d\n", *ptr1);
printf("ptr2 = %d\n", *ptr2);
printf("ptr3 = %d\n", *ptr3);
} while (0);
if (ptr1 != NULL) free(ptr1);
if (ptr2 != NULL) free(ptr2);
if (ptr3 != NULL) free(ptr3);
printf("内存已统一释放\n");
}
int main() {
useDoWhileFree(1);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int *createArray(int size) {
int *arr = (int *)malloc(size * sizeof(int));
return arr;
}
void destroyArray(int *arr) {
if (arr != NULL) {
free(arr);
}
}
void useFunctionEncapsulation() {
printf("=== 东巴文使用函数封装 ===\n\n");
int size = 5;
int *arr = createArray(size);
if (arr != NULL) {
// 使用数组...
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
printf("数组内容:\n");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
destroyArray(arr);
arr = NULL;
}
printf("内存已正确释放\n");
}
int main() {
useFunctionEncapsulation();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *ptr;
} SmartPointer;
SmartPointer createSmartPointer() {
SmartPointer sp;
sp.ptr = (int *)malloc(sizeof(int));
return sp;
}
void destroySmartPointer(SmartPointer *sp) {
if (sp != NULL && sp->ptr != NULL) {
free(sp->ptr);
sp->ptr = NULL;
}
}
void useSmartPointer() {
printf("=== 东巴文使用智能指针思想 ===\n\n");
SmartPointer sp = createSmartPointer();
if (sp.ptr != NULL) {
*sp.ptr = 100;
printf("sp.ptr = %d\n", *sp.ptr);
}
destroySmartPointer(&sp);
printf("内存已自动释放\n");
}
int main() {
useSmartPointer();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
// 内存分配计数器
static int allocationCount = 0;
void *trackedMalloc(size_t size) {
void *ptr = malloc(size);
if (ptr != NULL) {
allocationCount++;
printf("分配内存:%p (总数:%d)\n", ptr, allocationCount);
}
return ptr;
}
void trackedFree(void *ptr) {
if (ptr != NULL) {
allocationCount--;
printf("释放内存:%p (总数:%d)\n", ptr, allocationCount);
free(ptr);
}
}
void manualDetection() {
printf("=== 东巴文手动检测 ===\n\n");
int *ptr1 = (int *)trackedMalloc(sizeof(int));
int *ptr2 = (int *)trackedMalloc(sizeof(int));
*ptr1 = 100;
*ptr2 = 200;
printf("ptr1 = %d\n", *ptr1);
printf("ptr2 = %d\n", *ptr2);
trackedFree(ptr1);
// trackedFree(ptr2); // 忘记释放
printf("\n最终分配计数:%d\n", allocationCount);
if (allocationCount > 0) {
printf("警告:存在内存泄漏!\n");
}
}
int main() {
manualDetection();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void valgrindExample() {
printf("=== 东巴文Valgrind检测 ===\n\n");
int *ptr = (int *)malloc(sizeof(int));
*ptr = 100;
printf("ptr = %d\n", *ptr);
// 忘记 free(ptr);
printf("使用Valgrind检测:\n");
printf(" 编译:gcc -g program.c -o program\n");
printf(" 检测:valgrind --leak-check=full ./program\n");
}
int main() {
valgrindExample();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
void addressSanitizerExample() {
printf("=== 东巴文AddressSanitizer检测 ===\n\n");
int *ptr = (int *)malloc(sizeof(int));
*ptr = 100;
printf("ptr = %d\n", *ptr);
// 忘记 free(ptr);
printf("使用AddressSanitizer检测:\n");
printf(" 编译:gcc -fsanitize=address -g program.c -o program\n");
printf(" 运行:./program\n");
}
int main() {
addressSanitizerExample();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("=== 东巴文配对使用malloc和free ===\n\n");
// ✅ 正确:每个malloc对应一个free
int *ptr1 = (int *)malloc(sizeof(int));
int *ptr2 = (int *)calloc(5, sizeof(int));
int *ptr3 = (int *)realloc(NULL, sizeof(int));
free(ptr1);
free(ptr2);
free(ptr3);
ptr1 = NULL;
ptr2 = NULL;
ptr3 = NULL;
printf("内存正确配对释放\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("=== 东巴文释放后置NULL ===\n\n");
int *ptr = (int *)malloc(sizeof(int));
*ptr = 100;
printf("ptr = %d\n", *ptr);
free(ptr);
// ✅ 正确:释放后置NULL
ptr = NULL;
// 安全:释放NULL是安全的
free(ptr);
printf("正确处理悬空指针\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("=== 东巴文检查返回值 ===\n\n");
// ✅ 正确:检查返回值
int *ptr = (int *)malloc(sizeof(int));
if (ptr != NULL) {
*ptr = 100;
printf("ptr = %d\n", *ptr);
free(ptr);
ptr = NULL;
} else {
printf("内存分配失败!\n");
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define POOL_SIZE 100
typedef struct {
int data[POOL_SIZE];
int used;
} MemoryPool;
void initPool(MemoryPool *pool) {
pool->used = 0;
}
int *allocateFromPool(MemoryPool *pool) {
if (pool->used < POOL_SIZE) {
return &pool->data[pool->used++];
}
return NULL;
}
void useMemoryPool() {
printf("=== 东巴文使用内存池 ===\n\n");
MemoryPool pool;
initPool(&pool);
// 从内存池分配
int *ptr1 = allocateFromPool(&pool);
int *ptr2 = allocateFromPool(&pool);
if (ptr1 != NULL) *ptr1 = 100;
if (ptr2 != NULL) *ptr2 = 200;
printf("ptr1 = %d\n", *ptr1);
printf("ptr2 = %d\n", *ptr2);
printf("\n内存池优势:\n");
printf(" - 减少内存碎片\n");
printf(" - 提高分配效率\n");
printf(" - 便于管理\n");
printf(" - 避免内存泄漏\n");
}
int main() {
useMemoryPool();
return 0;
}
完成本章学习后,请确认:
掌握内存泄漏与防范后,你可以继续学习:
如果遇到问题,欢迎访问 东巴文(db-w.cn) 获取帮助!
东巴文(db-w.cn) - 让编程学习更简单
🎯 东巴文内存泄漏提示:内存泄漏是程序的隐形杀手。在 db-w.cn,我们会通过大量实例帮你掌握内存泄漏的防范技巧!