C语言按需分配字符串数组读取文件出现realloc invalid next size错误如何解决
代码问题分析
核心错误点
- realloc分配容量不足,导致堆内存越界写入
初始时array仅分配了1个char*指针的空间,仅能存储idx=0的元素。当你存入第1个元素后idx自增为1,此时执行realloc(array, idx * sizeof(char **))仅分配了1个指针的空间,无法容纳下一次要写入的idx=1位置的元素。后续每一步写入都存在越界,会破坏堆内存的元数据,直到调用realloc时检测到堆结构损坏就抛出invalid next size错误。
正确的扩容逻辑应该是:存入新元素前或自增idx后,分配idx+1个指针的空间。 - 字符串分配大小类型错误
代码*(array + idx) = malloc(LENGTH * sizeof(char *));中,存储字符串应该按char类型大小分配,此处误用了char*的大小,虽然实际分配的空间足够存储短字符串,但属于逻辑错误,正确写法应为malloc(LENGTH * sizeof(char))或直接按实际读取到的行长度分配malloc(strlen(result)+1)。 - 越界读取错误
循环结束后的判断if (*(array + idx) == NULL)属于非法越界访问,array的有效下标范围是0~idx-1,访问下标idx的位置属于越界读,会引发未定义行为。 - 内存泄漏问题
readLine函数中如果传入的len参数为NULL,你手动malloc了size_t类型的临时变量,但从未释放,会造成内存泄漏。readLine返回的line是getline动态分配的内存,你在readFile中拷贝完字符串后没有free对应的result指针,会造成内存泄漏。
- 换行处理逻辑缺陷
readLine中直接删除字符串最后一个字符的逻辑没有判断最后一个字符是否是换行符\n,如果文件最后一行没有末尾换行,会错误删除有效内容。
修复后的核心代码示例
// 修复后的readFile函数 char **readFile(const char *filename, size_t *fileLen) { char *result; int idx = 0; char **array = NULL; // 初始设为NULL,realloc可以直接处理NULL指针 if (filename == NULL || fileLen == NULL) { return NULL; } FILE *f = fopen(filename, "r"); if (f == NULL) { return NULL; } while (1) { size_t lineLen = 0; result = readLine(f, &lineLen); if (result == NULL) break; // 先扩容再存数据,扩容大小为idx+1 char **new_array = realloc(array, (idx + 1) * sizeof(char*)); if (new_array == NULL) { // 扩容失败处理,释放已有资源 for (int i = 0; i < idx; i++) free(array[i]); free(array); fclose(f); *fileLen = 0; return NULL; } array = new_array; // 直接按实际行长度分配,不需要预分配256字节 array[idx] = malloc(lineLen + 1); strcpy(array[idx], result); free(result); // 释放readLine中getline分配的内存 idx++; } fclose(f); *fileLen = idx; return array; } // 修复后的readLine换行处理逻辑 if ((nread = getline(&line, len, f)) != -1) { size_t lineLen = strlen(line); if (lineLen > 0 && line[lineLen - 1] == '\n') { line[lineLen - 1] = '\0'; // 直接替换结束符,不需要memmove } *len = strlen(line); return line; }
内容的提问来源于stack exchange,提问作者Samir
相关产品推荐
相关产品推荐

