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

calloc后使用realloc触发运行时错误,求解决方法

问题

在VS2022 C++14环境中学习C语言的malloc()、calloc()和realloc()函数时,代码输出符合预期,但触发运行时错误:

Invalid address specified to RtlValidateHeap( 01150000, 01155D20 ) A breakpoint instruction (__debugbreak() statement or a similar call) was executed in filaname.cpp

曾尝试谷歌搜索、观看教学视频、查阅Stack Overflow案例,但多数案例涉及C++和结构体,作为C语言初学者难以理解;也了解过realloc()的最佳实践,但问题仍存在,怀疑是free()使用不当但找不到具体问题点。

代码

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv)
{
    int* pm = (int*)malloc(sizeof(int) * 4);
    if (pm)
    {
        for (int i = 0; i < 4; i++)
        {
            *(pm + i) = i;
            printf("pm+i is : %p --- *pm+i is : %d\n", pm + i, *(pm + i));
        }
    }
    else
    {
        printf("malloc() failed.\n\n");
        return 1;
    }
    free(pm);
    printf("\n\n\n");

    int* pc = (int*)calloc(4, sizeof(int));
    if (pc)
    {
        for (int i = 0; i < 4; i++)
        {
            *(pc + i) = i * 2;
            printf("pc+i is : %p --- *pc+i is : %d\n", pc + i, *(pc + i));
        }
    }
    else
    {
        printf("calloc() failed.\n\n");
        return 1;
    }
    //free(pc); realloc() will free pc for me if needed .

    int* temp = (int*)realloc(pc, sizeof(int) * 8);
    if (temp)
    {
        pc = temp;
        //Should i free(temp) here?
        for (int i = 0; i < 8; i++)
        {
            *(pc + i) = i * 4;
            printf("pc+i is : %p --- *pc+i is : %d\n", pc + i, *(pc + i));
        }
    }
    else
    {
        printf("recalloc() failed.\n\n");
        return 1;
    }
    free(temp);
    free(pc);

    return 0;
}

程序输出

pm+i is : 01155D40 --- *pm+i is : 0
pm+i is : 01155D44 --- *pm+i is : 1
pm+i is : 01155D48 --- *pm+i is : 2
pm+i is : 01155D4C --- *pm+i is : 3



pc+i is : 01155D40 --- *pc+i is : 0
pc+i is : 01155D44 --- *pc+i is : 2
pc+i is : 01155D48 --- *pc+i is : 4
pc+i is : 01155D4C --- *pc+i is : 6
pc+i is : 01155D40 --- *pc+i is : 0
pc+i is : 01155D44 --- *pc+i is : 4
pc+i is : 01155D48 --- *pc+i is : 8
pc+i is : 01155D4C --- *pc+i is : 12
pc+i is : 01155D50 --- *pc+i is : 16
pc+i is : 01155D54 --- *pc+i is : 20
pc+i is : 01155D58 --- *pc+i is : 24
pc+i is : 01155D5C --- *pc+i is : 28

C:\Users\Strakizzz\Desktop\C\My Codeschool Projects\Pointers in C?C++\Debug\13_Dynamic memory allocation in C - malloc calloc realloc free.exe (process 368) exited with code -1.
To automatically close the console when debugging stops, enable Tools->Options->Debugging->Automatically close the console when debugging stops.
Press any key to close this window . . .

调试时程序停止并加载符号,关闭反汇编窗口后自动打开debug_heap.cpp文件。


问题分析与解决

核心错误:重复释放内存

代码中free(temp)和free(pc)属于重复释放同一块内存,这是触发堆验证错误的直接原因:

  • 当realloc成功时,若内存可原地扩容,temp与pc指向同一块内存;若需重新分配内存,realloc会自动释放原pc指向的内存,此时temp是新内存地址,而你已经执行pc = temp,所以pc和temp仍指向同一块内存。
  • 无论哪种情况,temp和pc最终指向同一内存块,连续调用两次free会破坏堆结构,触发运行时错误。

另外你代码中的注释//Should i free(temp) here?是误区:当pc = temp后,temp和pc是同一地址的别名,不需要单独释放temp,只需最后释放pc即可。

修正后的代码

#include<stdio.h>
#include<stdlib.h>

int main(int argc, char** argv)
{
    int* pm = (int*)malloc(sizeof(int) * 4);
    if (pm)
    {
        for (int i = 0; i < 4; i++)
        {
            *(pm + i) = i;
            printf("pm+i is : %p --- *pm+i is : %d\n", pm + i, *(pm + i));
        }
    }
    else
    {
        printf("malloc() failed.\n\n");
        return 1;
    }
    free(pm);
    printf("\n\n\n");

    int* pc = (int*)calloc(4, sizeof(int));
    if (pc)
    {
        for (int i = 0; i < 4; i++)
        {
            *(pc + i) = i * 2;
            printf("pc+i is : %p --- *pc+i is : %d\n", pc + i, *(pc + i));
        }
    }
    else
    {
        printf("calloc() failed.\n\n");
        return 1;
    }

    int* temp = (int*)realloc(pc, sizeof(int) * 8);
    if (temp)
    {
        pc = temp;
        for (int i = 0; i < 8; i++)
        {
            *(pc + i) = i * 4;
            printf("pc+i is : %p --- *pc+i is : %d\n", pc + i, *(pc + i));
        }
    }
    else
    {
        printf("realloc() failed.\n\n");
        // realloc失败时,原内存pc仍然有效,必须手动释放
        free(pc);
        return 1;
    }
    // 仅需释放pc,temp与pc指向同一块内存
    free(pc);

    return 0;
}

关键注意事项

  • realloc行为规则:
    • 成功时:若内存可原地扩容,返回原地址;若需新分配内存,返回新地址并自动释放原内存。
    • 失败时:返回NULL,原内存块不会被释放,必须手动释放原指针。
  • 避免重复释放:永远不要对同一内存地址调用多次free,也不要释放已被realloc自动释放的指针。
  • 指针赋值后不要重复操作:将temp赋值给pc后,两者是同一地址的别名,只需释放其中一个即可。

内容的提问来源于stack exchange,提问作者Sotiris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:36:07