C++动态分配与指针报错:CRT检测到堆缓冲区越界写入
问题分析与修复方案
Alright, let's break down exactly why you're hitting that "wrote to memory after end of heap buffer" error, and fix your code to do what you want (print every other character).
核心错误原因
Let's go through the bugs one by one:
- 内存分配严重不匹配: 你用
ptr = new char;只分配了1个字节的内存,但却让fgets往里面读最多100001个字符。这完全超出了堆缓冲区的范围——CRT检测到你在乱写不属于自己的内存,直接抛出了错误。 sizeof(ptr)理解错误:ptr是一个指针,sizeof(ptr)得到的是指针本身的大小(32位系统是4字节,64位是8字节),而不是它指向的缓冲区大小。你的循环只会跑4/8次,更关键的是,这根本不是获取缓冲区大小的正确方式。- 循环逻辑冗余: 你的循环里有两个
i++——一个在for声明里,一个在循环体内部。这会导致跳过的字符数超出预期,不过这是逻辑问题,不是崩溃的直接原因。 - 无限循环: 你用
char x = 1; while(x != 0)作为循环条件,但x的值从来没被修改过,循环会一直跑直到崩溃。
修复后的代码
下面是修正后的版本,关键修改都加了注释:
#include <iostream> #include <cstdio> // 用于fgets函数 using namespace std; int main() { const int BUFFER_SIZE = 100001; // 把缓冲区大小定义为常量,方便维护 char* ptr = nullptr; // 循环直到fgets读取失败(比如用户输入EOF,Windows用Ctrl+Z,Linux/macOS用Ctrl+D) while (true) { // 分配足够容纳最大输入量的内存 ptr = new char[BUFFER_SIZE]; // 检查fgets是否读取成功(遇到EOF或错误时返回NULL) if (fgets(ptr, BUFFER_SIZE, stdin) == nullptr) { delete[] ptr; // 退出前先释放内存 break; } // 遍历字符串,打印每隔一个字符 // 遇到字符串结束符'\0'就停止,避免读取超出字符串范围的内容 for (int i = 0; ptr[i] != '\0'; i += 2) { cout << ptr[i]; } cout << endl; // 用delete[]释放数组类型的分配(不能用delete!) delete[] ptr; ptr = nullptr; // 可选但属于良好编程习惯 } return 0; }
关键修复点说明
- 正确的内存分配: 我们用
new char[BUFFER_SIZE]分配了足够容纳100001个字符的缓冲区(包括fgets自动添加的字符串结束符)。 - 合理的循环条件: 不再依赖
sizeof(ptr),而是以字符串结束符'\0'作为循环终止条件,同时直接在for循环里让i每次加2,避免了重复递增的问题。 - 修复循环终止逻辑: 当
fgets返回NULL时(用户输入EOF或出现读取错误),循环就会退出,不会无限执行。 - 匹配的内存释放: 用
new[]分配的内存必须用delete[]释放,如果用普通delete会导致未定义行为。
这个版本应该能彻底解决CRT堆错误,同时正确实现你想要的“每隔一个字符输出”的功能。
内容的提问来源于stack exchange,提问作者NoobXDDD
相关产品推荐
相关产品推荐

