【问题标题】:Malloc inside a function call appears to be getting freed on return?函数调用中的 Malloc 似乎在返回时被释放?
【发布时间】:2010-09-11 10:52:21
【问题描述】:

我想我已经把它归结为最基本的情况:

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
>

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

【问题讨论】:

    标签: c pointers malloc


    【解决方案1】:

    您通过值而不是通过引用传递指针,因此无论您在 foo 中使用 arr 做什么都不会在 foo 函数之外产生影响。 正如 m_pGladiator 所写的那样,一种方法是声明对指针的引用(顺便说一句,仅在 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;
    }
    

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

    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;
    }
    

    【讨论】:

    • 我能不能说,请不要投malloc的返回值?它不是必需的,可以隐藏错误。
    • @freespace,这是我多年来养成的习惯。每个人,然后我都必须通过静态代码分析工具发送我的代码,他们抱怨没有转换指针。
    • 很抱歉让您在没有回复的情况下挂起:除非我轮询我所有的 cmets,否则没有好的方法可以在 cmets 中找到回复 :) 我已将答案留在 stackoverflow.com/questions/108768/…
    • @freespace,我知道 - 希望有一天能够添加通过 cmets 进行通知的功能。
    • 前两种中哪一种是使用函数分配内存最快的方法?
    【解决方案2】:

    您已在 foo 中分配了 arr,但该指针值存储在调用堆栈中。如果您想这样做,请这样做:

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

    在 main 中,只需传递一个指向 foo 的指针(如 foo(&arr))

    【讨论】:

      【解决方案3】:

      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)
      

      【讨论】:

        【解决方案4】:

        由于您是按值传递指针,因此 main 中的 arr 指针并未指向分配的内存。这意味着两件事:你自己有内存泄漏(不,在函数 foo 完成后内存没有被释放),当你访问 main 内的 arr 指针时,你正在访问一些任意范围的内存,因此你不要't get 3 打印出来,因此 free() 拒绝工作。很幸运,在 main 中访问 arr[3] 时没有遇到分段错误。

        【讨论】:

          【解决方案5】:

          如果参数 (arr) 不是通过引用 (&) 传入的,则不能更改它的值。一般来说,你会想要返回指针,所以你的方法应该是:

          arr=foo();

          尝试重新分配参数是不好的。我不推荐 (&) 解决方案。

          【讨论】:

            猜你喜欢
            • 2020-12-24
            • 1970-01-01
            • 2019-04-15
            • 2023-01-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-03-10
            • 2017-07-30
            相关资源
            最近更新 更多