函数调用中的Malloc似乎在返回时被释放?

时间:2020-03-06 14:27:45  来源:igfitidea点击:

我认为我已经将其归结为最基本的情况:

int main(int argc, char ** argv) {
  int * arr;

  foo(arr);
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

void foo(int * arr) {
  arr = (int*) malloc( sizeof(int)*25 );
  arr[3] = 69;
}

输出是这样的:

> ./a.out 
 car[3]=-1869558540
 a.out(4100) malloc: *** error for object 0x8fe01037: Non-aligned pointer
                         being freed
 *** set a breakpoint in malloc_error_break to debug
>

如果有人能阐明我的理解失败的地方,将不胜感激。

解决方案

我们已经在foo中分配了arr,但是指针值存储在调用堆栈中。如果要执行此操作,请按照以下步骤操作:

void foo( int ** arr) {
    *arr = (int *)malloc( sizeof(int) * 25 );
    (*arr)[3] = 69;
}

并且在主要方面,只需传递一个指向foo的指针(如foo(&arr))

我们通过值而不是通过引用传递指针,因此无论我们在foo内部对arr进行什么操作,都不会在foo函数之外产生任何影响。
正如m_pGladiator所写的那样,一种方法是这样声明对指针的引用(仅在C ++ btw中可能。C不了解引用):

int main(int argc, char ** argv) {
  int * arr;

  foo(arr);
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

void foo(int * &arr ) {
  arr = (int*) malloc( sizeof(int)*25 );
  arr[3] = 69;
}

另一种(更好的恕我直言)方式是不将指针作为参数传递而返回指针:

int main(int argc, char ** argv) {
  int * arr;

  arr = foo();
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

int * foo(void ) {
  int * arr;
  arr = (int*) malloc( sizeof(int)*25 );
  arr[3] = 69;
  return arr;
}

我们可以将指针传递给指针。这就是通过引用传递的C方法。语法有点复杂,但是C就是这样。

int main(int argc, char ** argv) {
  int * arr;

  foo(&arr);
  printf("car[3]=%d\n",arr[3]);
  free (arr);
  return 1;
}

void foo(int ** arr ) {
  (*arr) = (int*) malloc( sizeof(int)*25 );
  (*arr)[3] = 69;
}

如果未通过引用(&)传递参数,则不能更改其值(arr)。通常,我们需要返回指针,因此方法应为:

arr = foo();

试图重新分配论点是很糟糕的。我不建议使用(&)解决方案。

foo接收int指针的本地副本,将内存分配给它,并在超出范围时泄漏该内存。

解决此问题以使foo返回指针的一种方法:

int * foo() {
  return (int*) malloc( sizeof(int)*25 );
}

int main() {
    int* arr = foo();
}

另一个是将foo的指针传递给指针

void foo(int ** arr) {
   *arr = malloc(...);
}

int main() {
    foo(&arr);
}

在C ++中,修改foo以接受对指针的引用更为简单。我们需要在C ++中进行的唯一更改是将foo更改为

void foo(int * & arr)

由于我们要按值传递指针,因此main内部的arr指针不会指向已分配的内存。这意味着两件事:我们遇到了内存泄漏(不,在foo函数完成后不会释放内存),并且当我们访问main内部的arr指针时,我们正在访问任意范围的内存,因此我们不会不会打印出3个,因此free()拒绝工作。我们很幸运,在main内部访问arr [3]时没有遇到分段错误。