在递归函数中进行mallocing

时间:2016-01-28 18:58:08

标签: c recursion struct malloc

我有一个递归调用的函数很多次。在这个函数中,我将malloc内存用于结构,并将其作为参数传递给该函数的递归调用。我很困惑,我是否可以保持变量的名称我是mallocing相同。或者这会成为一个问题吗?

struct Student{
     char *studentName;
     int studentAge;
  };

recursiveFunction(*struct){ //(Whoever calls this function sends in a malloced struct)
    Student *structptr = malloc(sizeof(Student));
    <Do some processing>
             .
             .
   if(condition met){
       return;
   }
   else{
       recursiveFunction(structptr);
   }
}

free(){} // All malloced variables are free'd in another function

这是一个问题,因为malloced变量的名称在每次递归调用中都没有变化。

4 个答案:

答案 0 :(得分:1)

每个malloc()必须匹配free()。您需要释放recursiveFunction内的记录(例如,在退出之前),或者在recursiveFunction调用的函数中,或者您需要维护它们的列表并在其他地方释放它们。

'变量'malloced'的名称是相同的。在任何情况下,它都不是malloc() d的变量;而是存储在malloc() d的存储器和存储在变量中的地址。每个recursiveFunction的递归迭代都有不同的堆栈帧,因此是该变量的不同实例。因此,您需要做的就是确保每个malloc()与传递free()返回的地址的malloc()配对。

如果您想检查是否已完成malloc() / free()权限,请在代码上运行valgrind

答案 1 :(得分:1)

简短的回答是否定的。当你声明一个变量时,它的范围是在声明它的级别,在你的情况下是在这个函数中。每个连续的递归调用都会创建一个新的作用域并在该作用域内分配该内存,因此变量的名称不会导致问题。但是,您确实要非常小心,在从函数返回之前释放malloc()之前的任何内存,因为除非您传回指针,否则它将无法在函数范围之外访问。 This question提供了有关在函数中使用malloc()的大量有用信息。我还建议您在此处详细了解scope

答案 2 :(得分:0)

  

可以保持我正在进行mallocing变量的名称吗?

是的,在递归函数中,这很好。由于函数是递归调用的,每个包含malloc指针的变量(它不会保存内存本身)将被分配到一个新的堆栈帧上。

但是,你必须以某种方式释放那个记忆。只有指向内存的指针位于堆栈中,因此只有指针在函数退出时被释放。 malloc的记忆依然存在。在每次调用函数结束时,或者所有内存都必须作为更大结构的一部分返回并稍后释放。

答案 3 :(得分:0)

  

我很困惑,我是否可以保留变量的名称,我是mallocing相同的。

您似乎对scope的概念感到困惑。 C中的函数定义您在其中声明的(本地)变量的范围。这意味着当您在某个函数bar中声明局部变量foo时,当您在该函数中引用bar时,您将引用您声明的任何内容。

int bar = 21;
void foo(void) {
  int bar = 42;
  // ...
  bar; // This is the bar set to 42
}

现在范围只是理论概念。它是使用(我在这里跳过的其他细节)所谓的堆栈帧实现的:

当你调用foo时,会在调用堆栈上创建一个新的堆栈帧,其中包含(这在很大程度上取决于目标体系结构)返回地址(即将要执行的指令的地址)在foo之后),参数(即传递给函数的值),最重要的是,局部变量的空间(bar)。

使用地址 relative 当前堆栈帧,访问bar中的变量foo。因此,访问bar可能意味着相对于当前堆栈帧访问字节12。

当函数调用自身的递归函数时,这与任何其他函数调用一样处理(主要是,除了可能的优化),因此创建了一个新的堆栈帧。从不同的堆栈帧中访问相同(命名)变量将(因为,如上所述,访问使用相对地址)从而访问不同的实体。

[注意:我希望这个相当粗略的描述可以帮助您,这是一个主题 - 深入讨论时 - 极其依赖于实际的实现(编译器),使用的优化,调用约定,操作系统,目标架构,......]

我把一个简单的愚蠢的例子放在一起,希望表明你应该做的事情应该是可能的,因为你适当地free分配了什么:

unsigned int crazy_factorial(unsigned int const * const n) {
    unsigned int result;
    if (*n == 0) {
        result = 1;
    } else {
        unsigned int * const nextN = malloc(sizeof(unsigned int));
        *nextN = *n - 1;
        result = *n * crazy_factorial(nextN);
        free(nextN);
    }
    return result;
}

Running this with some output显示了正在发生的事情。