Windows下C语言内存泄漏测试时出现错误弹窗的排查求助
问题描述
在Windows环境下测试C语言内存泄漏场景时遇到问题,测试代码如下:
// cl /Zi /Fe.\build\main.exe /Fo.\build\main.o .\src\main.c #define _CRTDBG_MAP_ALLOC #include <crtdbg.h> #include <stdio.h> #include <stdlib.h> int* alloc_memory(size_t capacity) { int *ptr = malloc(sizeof(int) * capacity); return ptr; } int main(void) { //_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_WNDW); printf("- Memory Leak Test [id:0003] -\n"); int element_count = 5; int *arr = alloc_memory(element_count); for(size_t i = 0; i < element_count; i++) { arr[i] = i*10; } printf("- Output(1) -\n"); for(size_t i = 0; i < element_count; i++) { printf("address of arr: %p, value of arr: %d\n", &arr[i], arr[i]); } printf("- Output(2) -\n"); for(size_t i = 0; i < element_count; i++) { printf("address of arr: %p, value of arr: %d\n", arr, *arr); arr++; } free(arr); _CrtDumpMemoryLeaks(); return 0; }
在CMD中执行编译运行命令:
cl /Zi /MTd /Fe.\build\main.exe /Fo.\build\main.o .\src\main.c && .\build\main.exe
程序控制台输出正常:
- Memory Leak Test [id:0003] - - Output(1) - address of arr: 0000016700B90AA0, value of arr: 0 address of arr: 0000016700B90AA4, value of arr: 10 address of arr: 0000016700B90AA8, value of arr: 20 address of arr: 0000016700B90AAC, value of arr: 30 address of arr: 0000016700B90AB0, value of arr: 40 - Output(2) - address of arr: 0000016700B90AA0, value of arr: 0 address of arr: 0000016700B90AA4, value of arr: 10 address of arr: 0000016700B90AA8, value of arr: 20 address of arr: 0000016700B90AAC, value of arr: 30 address of arr: 0000016700B90AB0, value of arr: 40
但程序执行完毕后弹出错误对话框,需定位错误来源。
错误定位与解决
错误根源
弹窗的核心原因是堆内存损坏:
在Output(2)的循环中,arr++被执行了5次,导致arr指针最终指向了原数组末尾的下一个地址(而非malloc返回的原始地址)。此时调用free(arr),相当于尝试释放一个从未被malloc分配的地址,触发了CRT的堆内存检测机制,因此弹出错误对话框。
修复方案
有两种常见的修复方式:
方案1:保存原始指针
在分配内存后,立即保存malloc返回的原始地址,后续操作使用副本指针,最后释放原始地址:
int main(void) { // ... 其他代码不变 int element_count = 5; int *arr = alloc_memory(element_count); int *original_arr = arr; // 保存原始指针 // ... 赋值和Output(1)循环不变 printf("- Output(2) -\n"); for(size_t i = 0; i < element_count; i++) { printf("address of arr: %p, value of arr: %d\n", arr, *arr); arr++; } free(original_arr); // 释放原始地址 _CrtDumpMemoryLeaks(); return 0; }
方案2:不移动原始指针
修改Output(2)的循环逻辑,通过索引计算地址,避免修改arr的原始指向:
printf("- Output(2) -\n"); for(size_t i = 0; i < element_count; i++) { printf("address of arr: %p, value of arr: %d\n", arr + i, *(arr + i)); // 移除arr++,改用arr+i访问对应元素 } free(arr); // 此时arr仍是原始地址,释放合法
额外说明
修复后,_CrtDumpMemoryLeaks()会正确检测到内存无泄漏(如果使用方案1或2),同时不会再弹出堆损坏的错误对话框。
内容的提问来源于stack exchange,提问作者mbilyanov
相关产品推荐
相关产品推荐

