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
相关产品推荐
相关产品推荐

