调用realloc扩容char**后程序崩溃,求排查与解决
问题分析与修复
核心错误点
- 内存分配单位错误:
malloc(size * sizeof(char))和realloc(words, size * sizeof(char))中,words是char**类型,每个元素是指针,应该用sizeof(char*)计算每个元素的内存大小。 - 非法释放野指针:循环中
i++后立即执行free(words[i]),此时words[i]未被分配内存,属于野指针,直接触发内存访问错误。 - 字符串缺少终止符:
strncpy仅复制指定长度的字符,不会自动添加'\0',若输入单词长度等于maxLength,复制后的字符串无终止符,会导致内存越界。 - 输入缓冲区溢出:
fscanf("%s", line)未限制读取长度,当输入单词超过maxLength时,会溢出line数组,破坏栈内存。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #define S 8 char ** readLines(int * wordCountp, int maxLength) { char line[maxLength + 1]; int size = S; // 修正:用sizeof(char*)分配指针数组内存 char ** words = malloc(size * sizeof(char*)); if (words == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } int i = 0; // 修正:构造限制长度的格式字符串,避免line缓冲区溢出 char fmt[32]; snprintf(fmt, sizeof(fmt), "%%%ds", maxLength); while (fscanf(stdin, fmt, line) == 1) { words[i] = malloc((maxLength + 1) * sizeof(char)); if (words[i] == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } // 修正:复制后手动添加终止符 strncpy(words[i], line, maxLength); words[i][maxLength] = '\0'; i++; if (i == size) { size *= 2; // 修正:用sizeof(char*)扩容指针数组,并用临时变量接收结果避免内存丢失 char ** temp = realloc(words, size * sizeof(char*)); if (temp == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(1); } words = temp; } } // 确保指针数组末尾为NULL,作为结束标记 if (i < size) { words[i] = NULL; } *wordCountp = i; return words; }
关键修改说明
- 内存分配修正:将
sizeof(char)替换为sizeof(char*),确保指针数组的每个元素都能容纳一个char*指针。 - 移除非法free:删除循环中的
free(words[i]),保留读取到的字符串内存。 - 添加字符串终止符:复制完成后手动设置
words[i][maxLength] = '\0',保证字符串正确终止。 - 限制输入长度:通过
snprintf构造格式字符串"%Ns"(N为maxLength),让fscanf最多读取maxLength个字符,避免line数组溢出。 - 安全扩容:用临时变量
temp接收realloc的返回值,避免realloc失败时丢失原指针指向的内存。
内容的提问来源于stack exchange,提问作者user20946097
相关产品推荐
相关产品推荐

