微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Calloc 在不同的计算机上表现不同

如何解决Calloc 在不同的计算机上表现不同

我已经用 C 编写了以下代码

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

int func(int n,int * data){
  for(int i = 1; i <= n; i++){
    data = realloc(data,i * sizeof(int));
    data[i - 1] = i;
  }
  return 0;
}

int main(void){

  int numb = 10;
  int * array = calloc(1,sizeof(int));
  func(numb,array);

  for(int j = 0; j < numb; j++){
    printf("%d \t",array[j]);
  }

  free(array);
  return 0;
}

在第一台计算机上,输出符合预期:

1 2 3 4 5 6 7 8 9 10

现在,如果我在另一台计算机上编译并运行相同的程序,它会输出随机整数值。我在这里缺少什么?我做错了什么?为什么相同的程序在不同的计算机上有不同的行为?

解决方法

此程序的行为未定义。如果它在任何计算机上打印出您所期望的内容,那纯属巧合。

  int * array = calloc(1,sizeof(int));
  func(numb,array);

您在这里传递 array 按值,这意味着 func 对它所做的任何事情对于外部作用域都是不可见的。请注意,realloc 不能保证返回相同的指针,因此您需要预期 array 在调用过程中会发生变化。尝试将指针传递给 array

int func(int n,int ** data){
  for(int i = 1; i <= n; i++){
    *data = realloc(*data,i * sizeof(int));
    (*data)[i - 1] = i;
  }
  return 0;
}

...

    func(numb,&array);
,

根据 Ian Abbot 的评论,您可以做的最小修正是让 func() 返回新分配的块:

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

int * func(int n,int * data)  // <-- Notice the * in the return value
{
  for(int i = 1; i <= n; i++){
    data = realloc(data,i * sizeof(int));
    data[i - 1] = i;
  }
  return data; // <-- We return a pointer to the newly allocated memory block
}

int main(void)
{
  int numb = 10;
  int * array = calloc(1,sizeof(int));
  array = func(numb,array); // <-- reassign to array (same pattern as realloc)

  for(int j = 0; j < numb; j++){
    printf("%d \t",array[j]);
  }

  free(array);
  return 0;
}

通过这种方式,您可以确定如果 realloc() 更改了内存块的位置,它会在数组中更新。

,

您的程序有未定义的行为。因此,即使在同一台计算机中,它也可能具有不同的行为......让我解释一下:

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

int func(int n,int * data){
  for(int i = 1; i <= n; i++){
    // HERE,YOU CHANGE THE VALUE OF data FOR THE NEW
    // VALUE RETURNED BY REALLOC.  As the value ov array
    // was copied on entry,it is not known outside of
    // func()
    data = realloc(data,i * sizeof(int));
    data[i - 1] = i;
  }
  return 0;
  // AFTER THIS POINT THE ORIGINAL (the passed in value
  // to func() is not valid anymore
}

int main(void){

  int numb = 10;
  int * array = calloc(1,array);
  // at this point,the value of array is not valid,// in case the value realloc() has returned inside
  // func() has changed.

  for(int j = 0; j < numb; j++){
    printf("%d \t",array[j]);
  }

  // THIS IS ALSO INCORRECT.
  free(array);
  return 0;
}

解决您的问题的方法是您返回 返回新值(calloc() 返回的值),如

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

int *func(int n,int * data){
  for(int i = 1; i <= n; i++){
    data = realloc(data,i * sizeof(int));
    data[i - 1] = i;
  }
  return data;
}

int main(void){

  int numb = 10;
  int * array = calloc(1,sizeof(int));
  // now array continues to be bvalid after the call to func().
  array = func(numb,array);

  for(int j = 0; j < numb; j++){
    printf("%d \t",array[j]);
  }

  free(array);
  return 0;
}

顺便说一句,为了达到最佳状态,并且您知道 ifunc() (n) 中将采用的最终值,您应该写 func() 只对 realloc() 进行一次调用,这比为每个值重新分配一次要快。

int *func(int n,int *data) {
  data = realloc(data,n * sizeof *data);
  for (int i = 1; i <= n; i++)
    data[i-1] = i;
  return data;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。