重新分配内存不复制旧数据

3

背景:

我使用calloc()创建了一个数组,一切都很顺利。然后,我使用realloc()将数组变大。它似乎只是创建了一个新指针,里面没有任何内容,在我尝试访问数组元素时会调用运行时错误。

我的代码:

#include <stdio.h>

int main() {

  int *arr;

  for (int i = 0; i < 5; i++){
      if (i == 0) {
          if ((arr = (int *) calloc(1, sizeof(int))) == NULL) {
              printf("NO MORE SPACE TERMINATING PROGRAM");

              return NULL;
          }

      } else {
          int *tmp;

          if ((tmp = (int *)realloc(arr, 4*sizeof(int)) == NULL)){
              printf("NO MORE SPACE TERMINATING PROGRAM");
          }

          arr = tmp;
      }

      arr[i] = i;
  }
}

当i等于1时,在arr[i]=i;这一行会抛出运行时错误。

当我在arr = temp;上面添加一个断点时,它显示temp完全为空。

为什么会发生这种情况?

--------更新----------------

感谢所有的帮助。以下是已经调试好的代码:

#include <stdio.h>
#include <stdlib.h>

int main(){
    int *arr = NULL;

    for (int i = 0; i < 5; i++){
        int *tmp;

        if ((tmp = realloc(arr, (i+1) * sizeof(int))) == NULL){
            printf("NO MORE SPACE TERMINATING PROGRAM");
        }

        arr = tmp;

        arr[i] = i;
    }

    for (int i = 0; i < 5; i++) {
        printf("%i",arr[i]);
    }
}

输出结果为:01234
感谢大家的帮助。

5
你没有包含 #include <stdlib.h>,这就是为什么你不应该强制转换 malloccallocrealloc 的结果的原因。另外,arr[4] 超出了你重新分配的 4 个元素的范围(3 是用 4 个元素的数组可以访问的最大索引)。 - Kninnug
2
与您的问题无关,但如果您最初使用了int *arr = NULL;,那么i == 0情况是多余的。重新分配空指针是安全的,并且在这种情况下它的行为与malloc相同。 - M.M
此外,从风格的角度来看,for (i = 0; ___; i++) { if (i == 0) {....} 更清晰的写法是将 {....} 块放在循环开始之前。 - M.M
1个回答

5

始终注意警告信息。这样做会显示:

warning: assignment makes pointer from integer without a cast [enabled by default]
           if ((tmp = (int *)realloc(arr, 4*sizeof(int)) == NULL)){

这告诉你编译器正在将一个int分配给tmp。这怎么可能呢?如果你仔细看,你会发现括号不正确。实际上,它将realloc(arr, 4*sizeof(int)) == NULL的结果赋值给了tmp。下面是正确的代码。请注意赋值周围的括号。

if ((tmp = realloc(arr, 4*sizeof(int))) == NULL)

你需要添加 #include <stdlib.h> 头文件以便使用 callocrealloc 函数。
更新:根据 M.M 和其他人的建议,即使上述问题已经解决,realloc 仍然不正确,因为它只分配了4个元素,而 for 循环将访问5个元素。所以需要将 4 改为 5 或者 i+1。虽然这不会导致任何功能问题,但在0之后的每次循环中进行 realloc 是不必要的。

也许最好提一下 4 不够用,或许 (i+1) 更好。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接