释放堆分配内存时触发HEAP CORRUPTION DETECTED错误求助
堆损坏问题的原因及修复方案
1. buffer数组越界写入(直接触发堆损坏)
在readLine函数中,你为*buffer分配了*bufferSize字节内存,但随后执行(*buffer)[(*bufferSize)] = '\0';——该索引超出了内存分配范围(分配的内存索引仅到*bufferSize-1),直接破坏堆结构,导致HEAP CORRUPTION DETECTED错误。
修复方法:分配内存时多留1个字节给字符串终止符:
*buffer = (char*)malloc(sizeof(char) * (*bufferSize + 1)); if (*buffer != NULL) { memcpy(*buffer, tempBuffer, *bufferSize); (*buffer)[*bufferSize] = '\0'; }
2. main循环中未释放旧buffer的内存泄漏
每次调用readLine都会重新分配*buffer,但之前分配的buffer内存未被释放,不仅造成内存泄漏,还可能导致后续指针覆盖引发的非法访问。
修复方法:调用readLine前检查并释放旧buffer:
do { if (buffer != NULL) { free(buffer); buffer = NULL; } lastLine = readLine(&inputStream, &buffer, &bufferSize); // 后续逻辑 } while (!lastLine);
3. reverse数组分配空间不足
当lastLine为0时,你会额外写入'\n'和终止符'\0',但原分配的reverse大小仅为bufferSize,会导致越界写入。
修复方法:根据是否需要换行符计算正确的分配大小:
int reverseSize = bufferSize + (lastLine ? 0 : 1) + 1; reverse = (char*)malloc(sizeof(char) * reverseSize);
4. feof循环导致的空读取问题
while (!feof(intputStream))会在读取到EOF后仍执行一次循环,此时tempBuffer为空,malloc(0)行为未定义,可能引发非法访问。
修复方法:改为通过readLine返回的lastLine标记控制循环,同时在readLine中先判断fgets是否读取成功:
// readLine函数内新增判断 if (fgets(tempBuffer, BUFFER_SIZE, *stream) == NULL) { *bufferSize = 0; *buffer = NULL; return 1; // 标记为最后一行 }
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFFER_SIZE 255 int readLine(FILE** stream, char** buffer, int* bufferSize); void reverseString(char* buffer, char** reverse, int bufferSize, int lastLine); int main(int argc, char** argv) { char* buffer = NULL; char* reverse = NULL; int bufferSize = 0; int lastLine = 0; if (argc < 3) { printf("Usage: %s <input file> <output file>\n", argv[0]); return 1; } FILE* inputStream = fopen(argv[1], "r"); FILE* outputStream = fopen(argv[2], "w"); if (inputStream == NULL || outputStream == NULL) { printf("Input or output file cannot be opened\n"); return 1; } do { if (buffer != NULL) { free(buffer); buffer = NULL; } lastLine = readLine(&inputStream, &buffer, &bufferSize); if (bufferSize > 0) { int reverseSize = bufferSize + (lastLine ? 0 : 1) + 1; reverse = (char*)malloc(sizeof(char) * reverseSize); if (reverse != NULL) { reverseString(buffer, &reverse, bufferSize, lastLine); fputs(reverse, outputStream); free(reverse); reverse = NULL; } } } while (!lastLine); fclose(inputStream); fclose(outputStream); if (buffer != NULL) free(buffer); return 0; } int readLine(FILE** stream, char** buffer, int* bufferSize) { char tempBuffer[BUFFER_SIZE] = { 0 }; int lastLine = 0; if (*stream == NULL) return 1; if (fgets(tempBuffer, BUFFER_SIZE, *stream) == NULL) { *bufferSize = 0; *buffer = NULL; return 1; } *bufferSize = strlen(tempBuffer); char ignoredChar[100] = { 0 }; if (tempBuffer[*bufferSize - 1] != '\n') { while (fgets(ignoredChar, sizeof(ignoredChar), *stream) != NULL) { size_t len = strlen(ignoredChar); if (len > 0 && ignoredChar[len - 1] == '\n') break; } lastLine = feof(*stream) ? 1 : 0; } else { lastLine = 0; } *buffer = (char*)malloc(sizeof(char) * (*bufferSize + 1)); if (*buffer != NULL) { memcpy(*buffer, tempBuffer, *bufferSize); (*buffer)[*bufferSize] = '\0'; } return lastLine; } void reverseString(char* buffer, char** reverse, int bufferSize, int lastLine) { int startingValue = (lastLine ? bufferSize - 1 : bufferSize - 2); int wordStart = startingValue, wordEnd = startingValue; int index = 0; while (wordStart >= 0) { if (buffer[wordStart] == ' ') { for (int i = wordStart + 1; i <= wordEnd; i++) { (*reverse)[index++] = buffer[i]; } if (index < (int)(bufferSize + (lastLine ? 0 : 1))) { (*reverse)[index++] = ' '; } wordEnd = wordStart - 1; } wordStart--; } for (int i = 0; i <= wordEnd; i++) { (*reverse)[index++] = buffer[i]; } if (!lastLine) { (*reverse)[index++] = '\n'; } (*reverse)[index] = '\0'; }
内容的提问来源于stack exchange,提问作者user10203585
相关产品推荐
相关产品推荐

