You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 12:25:15