程序在重新分配到 char** 后挂起

Program hangs after reallocating into char**

提问人:user20946097 提问时间:1/7/2023 最后编辑:Geneuser20946097 更新时间:1/7/2023 访问量:67

问:

我正在尝试阅读行,直到 EOF。如果该行的长度大于 maxLength,则其余部分将被截断。 如果行数超过 S,则应重新分配双倍的行数。 在重新分配之前,一切正常。当它到达该部分时,程序崩溃。 我已经坐了 2 天了。

#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;
  char ** words = malloc(size * sizeof(char));
  if (words == NULL) {
    fprintf(stderr, "Memory allocation failed\n");
    exit(1);
  }
  int i = 0;
  while (fscanf(stdin, "%s", line) == 1) {
    words[i] = malloc((maxLength + 1) * sizeof(char));
    strncpy(words[i], line, maxLength);
    i++;
    if (i == size) {
      size *= 2;
      words = realloc(words, size * sizeof(char));
      if (words == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(1);
      }
    }
    if (words == NULL) {
      fprintf(stderr, "Memory allocation failed\n");
      exit(1);
    }
    free(words[i]);
  }
  words[i] = NULL;
  *wordCountp = i;
  return words;
}

分配而不是弄乱数组,但仍然不能解决问题。sizeof(char*)sizeof(char)

创建一个单独的,重新分配那个,然后将原始文件复制到其中也不起作用。char**

c 管理 malloc 动态内存分配 realloc

评论

0赞 afarrag 1/7/2023
在每次迭代结束时,你这样做有什么原因吗?free(words[i]);
1赞 Adrian Mole 1/7/2023
您必须将 (the sizeof(char)') 用于第一个和 (the sizeof(char)')。sizeof(char*)mallocreallocmalloc inside the loop is correctly using
0赞 Gene 1/7/2023
@AdrianMole说了什么。避免这种愚蠢错误的一个好方法是将分配的指针作为 : 的参数取消引用。与 相同。sizeofchar ** words = malloc(size * sizeof *words);realloc
0赞 chux - Reinstate Monica 1/7/2023
@Gene同意了。此外:虽然与 相同,但 与确保乘法是在更复杂的情况下使用数学完成的。与数学有区别,可能会溢出数学,但不会溢出数学。size * sizeof *wordssizeof *words * sizesizeof *wordssize_tint i, j; ... sizeof *words * i * ji * jintsize_t
0赞 Gene 1/7/2023
是的,在这个例子中,这并不重要。

答:

2赞 chux - Reinstate Monica 1/7/2023 #1

至少存在以下问题:

避免分配大小错误

分配给引用对象的大小,而不是类型的大小,这在这里是错误的。

//                               v----------v  Wrong type and too small 
// char ** words = malloc(size * sizeof(char));
char ** words = malloc(sizeof words[0] * size);
//                     ^-------------^ Just right  

// words = realloc(words, size * sizeof(char));
words = realloc(words, sizeof words[0] * size);

复制整个字符串

words[i] = malloc((maxLength + 1) * sizeof(char));
//                         v-------v  1 too short
// strncpy(words[i], line, maxLength);
strcpy(words[i], line);

使用 fgets() 读取一行

fscanf(stdin, "%s", line)不会读一,更像是会读一个。如果没有宽度,缓冲区可能会溢出。

// fscanf(stdin, "%s", line)
while (fgets(line, sizeof  line, stdin)) {

评论

0赞 user20946097 1/9/2023
谢谢,更改类型有效!虽然缓冲区溢出在这里不是问题,但我意识到 fscanf 在这个特定用例中有很多意外行为。
0赞 chux - Reinstate Monica 1/9/2023
@user20946097 我希望您的代码没有从一种类型更改为另一种类型。而是 .sizeof words[0] * size