【问题标题】:malloc() fails to allocate memory inside a function in Cmalloc() 无法在 C 中的函数内分配内存
【发布时间】:2020-01-26 09:43:35
【问题描述】:

我想在函数内部动态分配内存。该函数名为func_1,声明如下:

int func_1(int **destination);

这里destination是一个指向指针的指针。此指针包含我要在函数内部动态分配内存的指针的地址。

函数func_1的代码如下:

void func_1(int **destination)
{
   *destination = (int*)malloc(sizeof(int) * 10);
   for(int i = 0 ; i < 10 ; i++)
   {
      *destination[i] = i;             //segmentation fault comes HERE
   }    
}

下面是我的main()函数:

int main()
{
   int *pointer;
   func_1(&pointer);
   return 0;
}

当我尝试运行这个程序时,我得到一个分段错误 (SIGSEGV) 错误。我用GDB定位了这个错误的根源,结果发现for循环里面的那行是这个错误的罪魁祸首。

请注意,一旦函数退出,我希望保留分配给函数内部动态分配内存的值,这就是我传递要分配的指针地址的原因动态记忆。

我想知道:

  • 为什么会出现此错误?

  • 如何解决?

感谢您的帮助!

【问题讨论】:

  • 你忘了free()堆对象。

标签: c pointers


【解决方案1】:

[](数组下标)运算符的优先级为 2

*(取消引用)运算符的优先级为 3

在您的代码中,*destination[i] 的含义与 *(destination[i]) 相同。该值未初始化,会导致分段错误。

如果您将使用明确的操作优先级(*destination)[i],您将获得预期的结果。

void func_1(int **destination)
{
   *destination = (int*)malloc(sizeof(int) * 10);
   for(int i = 0 ; i < 10 ; i++)
   {
      (*destination)[i] = i;             //no segmentation fault
   }    
}

你可以阅读更多关于优先级here

完整代码:

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

void func_1(int **destination)
{
   *destination = (int*)malloc(sizeof(int) * 10);
   for(int i = 0 ; i < 10 ; i++)
   {
      (*destination)[i] = i;             
   }
}

int main()
{
   int *pointer;
   func_1(&pointer);
   return 0;
}

【讨论】:

  • 应用此解决方案确实消除了分段错误。
【解决方案2】:

为什么会出现这个错误?

您正在覆盖destination 指针,而不是将malloc 返回的值分配给destination 指针所指向的指针

  • 您应该输入**destination = malloc(sizeof(int) * 10),而不是*destination = (int*)malloc(sizeof(int) * 10)
  • 您应该输入(**destination)[i] = i,而不是*destination[i] = i

在 C 中,数组下标运算符 [] 的优先级高于间接运算符 *。除此之外,前者是从左到右结合,而后者是从右到左结合

在您的情况下,这意味着您需要输入 (**destination)[i] = i; 而不是 **destination[i] = i,因为否则 [i] 将在 ** 之前被评估,并且您最终会间接使用 wild pointer(这将导致分段错误在一般情况下极有可能发生,在这种情况下绝对肯定,因为您在 i == 0 时引用了一个空指针。


如何解决这个问题?

“让它工作”修复就是我上面介绍的那个。

但是,这并没有解决您的代码的根本问题,即它不必要地复杂。使用指向指针的指针非常容易出错,应该避免。实际上,在这种情况下根本不需要使用一个。

以下内容完全符合您的要求,没有所有不必要的复杂性:

int* func_1()
{
   int* destination = malloc(sizeof(int) * 10);
   for (int i = 0; i < 10; ++i)
   {
      destination[i] = i;
   }
   return destination;
}
int main()
{
   int* pointer = func_1();
   free(pointer);
   return 0;
}

请注意,一旦函数退出,我希望保留分配给函数内部动态分配内存的值,这就是我传递要分配的指针地址的原因动态记忆。

正如我上面演示的,没有理由将指针传递给指向函数的指针。用malloc 分配的内存是你永远使用的,你只需要跟踪它并在不再需要它时调用free 释放它。如何跟踪内存并不重要——在这种情况下,只需返回一个指针就足够了。在func_1 中修改pointer 而不是捕获函数的返回值并没有带来额外的好处,只会使代码变得比它需要的更复杂。


我的印象是您对指针有些困惑,因此我建议您修改主题。这是关于指针的非常清楚的解释,它还涵盖了指向指针的指针(以及指向指针的指针):How do pointers work in C?


阅读更多:

【讨论】:

    猜你喜欢
    • 2017-12-05
    • 2020-12-14
    • 1970-01-01
    • 2012-02-26
    • 2012-10-10
    • 2015-01-05
    • 2015-02-11
    • 1970-01-01
    • 2012-12-26
    相关资源
    最近更新 更多