在不使用 realloc 的情况下在 C 中增长数组?

Grow array in C without using realloc?

所以我尝试从 stdin 一次读入一个字节。 while 循环的每次迭代我都试图重新分配缓冲区,但我不想使用 realloc。这是我试过的:

   char tempChar = '[=10=]';
   char *buffer;
   int bufferSize = 0;


   buffer = (char*) malloc(sizeof(char));
   while((tempChar = getc(stdin)) != EOF)
   {
      buffer[bufferSize] = tempChar;
      bufferSize++;

      char *temp = buffer;
      buffer = (char*)malloc(sizeof(char)*bufferSize);
      memcpy(buffer, temp, sizeof(temp));
      free(temp);
   }
   buffer[bufferSize] = '[=10=]';

我遇到了分段错误。知道为什么会这样吗?

编辑:好的,我像其他人所说的那样修复了两个错误。这是固定版本:

  char tempChar = '[=11=]';
  char *buffer;
  int bufferSize = 1;
  int count = 0; 
  buffer = malloc(sizeof(char));

  while((tempChar = getc(stdin)) != EOF){
    buffer[count] = tempChar;
    count++;

    if(count >= bufferSize){
      bufferSize *= 2;
      char *temp = buffer;
      buffer = malloc(sizeof(char)*bufferSize);
      memcpy(buffer, temp, count);
      free(temp); 
    }
  }

  buffer[count - 1] = '[=11=]';

I get a segmentation fault. Any idea why that happens?

因为您正在写入超出分配的内存。

这就是 realloc 的用途。

您不需要在每次读取新字节时都调用 realloc 来增大缓冲区,而是每次需要增大时都将缓冲区的大小加倍,直到达到某个实际最大值,然后通知您的用户。这就是 C++ vector<T> 等数据结构的工作方式。

您的缓冲区太小了一个字节。这一行

  buffer = (char*)malloc(sizeof(char)*bufferSize);

应该阅读

  buffer = malloc(bufferSize + 1);

不要在 C 中从 malloc() 转换 return,根据定义 sizeof(char) 是一个。

另外,这是错误的:

  memcpy(buffer, temp, sizeof(temp));

复制的字节数等于char *.

的大小

这里出现分段错误的原因有两个。在开始之前,我必须提到每次读入一个额外的字节时分配一个新的缓冲区是非常低效的。分配一些合理大小的缓冲区,然后以合理大小的块扩展它几乎总是更可取的。

也就是说,您代码中的第一个问题是 memcpy(buffer, temp, sizeof(temp))。当您执行 sizeof(temp) 时,您将获得系统上指针的字节数。可能是 4 或 8。您在这里真正想要的是旧缓冲区的长度。最初这是一个问题,因为您的缓冲区开始时大小为 1 个字节。然后您尝试复制总共 4 或 8 个字节(可能),并非所有这些都是缓冲区的一部分。

其次,当您执行 buffer[bufferSize] = '[=12=]' 时,您实际上是将 [=13=] 写入缓冲区末尾后的字节。你会想为此使用 bufferSize - 1

您的代码中有两个错误。

1) memcpy(buffer, temp, sizeof(temp)); 这一行每次复制一个固定数量的字节。 sizeof(temp) 不是数组的分配大小,而是指针的大小,很可能是 4 或 8 个字节。因此,对于前几次迭代,您实际上写的比分配的 space 多,之后就是复制不够。您想要将 sizeof(temp) 替换为 bufferSize,与您用于分配缓冲区的值相同。

2) 最后你有 buffer[bufferSize] = '[=13=]';。然而,这是在分配的缓冲区末尾写入一个字节。 bufferbufferSize 字节,这意味着它的可寻址索引值为 0 - bufferSize-1。但是,用 buffer[bufferSize-1] 替换这一行会将最后一个字符替换为零终止符,因此您总是会丢失输入的最后一个字符。相反,您需要多分配 1 个字节。 我个人会将分配行替换为:

buffer = (char*)malloc(bufferSize+1);