在函数返回后,函数中分配的内存是否仍然保持分配状态?

时间:2014-08-29 12:07:20

标签: c arrays function malloc

对于以下代码: (1)“main”调用函数“f1”。 (2)功能“f1”进行一些数字处理;使用malloc创建一个“char”数组,然后将数组的指针返回给main(不分配-freeing-数组)。

我有3个与案件有关的问题: (1)我假设,虽然函数“f1”已经终止,但分配的char数组仍然保持分配状态,直到主程序完全终止。也就是说,分配的内存仍然属于主内存,没有其他进程可以从外部访问(我的意思是,干扰)它。我对吗? (2)在程序终止之前是否必须释放数组(在“f1”中分配)(或者在主程序终止后它是否会被释放)? (3)如果第二个问题的答案为“是”,那么如何释放在另一个函数中分配的数组呢?

注意:我希望保持在纯c的范围内,而不是溢出到c ++。

char *f1 (...) {
    ...
    ...
    char *fTmp = malloc (length1 * sizeof (char));
    char *fData = malloc (length2 * sizeof (char));
    ...
    ...
    free (fTmp);
    return (fData);
}

int main () {
    char *fData = f1 (...);
    ...
    return (0);
}

7 个答案:

答案 0 :(得分:17)

  

我假设,虽然功能" f1"已终止,分配的char数组仍然保持分配状态,直到主程序完全终止。

真。动态分配的内存与函数无关,它属于进程。

  

也就是说,分配的内存仍然属于main,没有其他进程可以从外部访问它。我是对的吗?

内存不属于main()(用作函数),而是处理自身(其中main()只是入口点)。在具有内存保护的系统中(每个进程与其他进程隔离),它无法从外部访问。但是,您可以以特定于系统的方式分配它,以跨进程共享内存。

  

我是否必须在程序终止之前释放数组(在" f1"中分配)(或者在主程序终止后立即释放)?

是。未分配的内存 - 大多数系统中的 - 在进程终止时由操作系统自动释放,但这取决于系统。 IMO甚至在操作系统执行时你应该总是解除分配,使用这种自动释放作为红旗(我忘记了解除分配,这是一个错误吗?我错过了什么?)。此外,如果f1被调用1000次,那么每次快速吃掉所有可用内存都会泄漏内存。考虑服务器中的进程,它可能(并且应该)启动并运行多年。

  

如果第二个问题的答案是"是"那么如何释放在另一个函数中分配的数组呢?

分配内存的人也可以释放它。如果不可能,则调用者将对此类内存负责。例如,它是strdup()的作用。在这种情况下,被调用的函数必须返回(以某种方式)指向已分配内存的指针(或可由另一个专用函数使用的句柄/令牌)。例如:

char* pBuffer = f1();
// Use it
free(pBuffer);

请注意,如果要隐藏此类内部指针,有许多技巧。您可以使用标记(例如,整数,字典中的键),typedef或不透明类型。

答案 1 :(得分:6)

  1. 是的,分配有malloc()的内存会一直保留,直到被释放。一个函数怎么能将可变大小的数据返回给它的调用者呢?

  2. 当程序退出时,将释放分配有malloc()的所有内存。但是,在程序终止之前保留大量不需要的内存通常不是一个好主意,因为它会影响性能,或者系统可能耗尽虚拟内存。这对于长时间运行的程序来说可能是一个特别关注的问题,它们的内存使用有时会持续增长,直到它们使用所有可用的虚拟内存。

  3. 您在函数返回的指针上调用free()。因此,在您的情况下,main()可以在使用数组完成free(fData)之后执行。{/ p>

  4. 任何C编程课程或教科书都应该涵盖这一点。

答案 2 :(得分:2)

malloc在堆上分配内存,因此这个内存保持分配状态,直到它被free函数释放,或者程序成功终止。
在您的情况下,您在ftemp中释放了f1,因此在函数终止后它不再存在。 fdata仍然在堆上,main可以访问它,因为您返回指向该分配位置的指针。

main成功终止后,fdata指向的内存将被释放。

因此,只要你不再需要记忆,就认为免费记忆是好的。在程序结束时释放块是没有意义的,因为当进程终止时(考虑到现代操作系统),所有程序的空间都被返回给系统。

答案 3 :(得分:1)

使用malloc将在堆上分配内存,直到它free为止。

这意味着您需要确保每个malloc都有相应的免费,也并不意味着没有其他进程无法访问您的数据。它只是一个地址的值。

在您的主要内容中,您必须free(fData)以避免内存泄漏。

总结一下:

1)你的第一个假设是正确的,第二个和第三个假设是正确的。它将保持分配状态,但它不是主要的本地,并且在终止时没有绑定到进程

2)是的,你必须释放它

3)使用从函数中获得的指针。如果没有从函数返回指向已分配数据的指针,请确保函数free为它。

答案 4 :(得分:1)

  1. 是的,它还在堆里。但是,您对流程的概念感到困惑。除非您创建另一个流程(在* nix上使用fork),否则它仍然是相同的流程。

  2. 在不使用时释放内存是一个好习惯。但是如果程序正常终止,系统将释放分配的内存。

  3. 像这样:

    int main () {
        char *fData = f1 (...);
        //...
        free(fData);
        //...
    }
    

答案 5 :(得分:1)

在C中可以使用两种基本类型的内存。两种类型是堆栈和堆。通常,在函数中创建的变量将在堆栈上分配,并在函数返回时释放。堆中分配的内存将保持不变,您有义务在程序中管理该分配。堆中的内存将保持分配状态,直到您使用引用数据块的指针(内存地址)释放为止。

对两者的一点阅读将有助于您理解。我要指出你有两个fData实例,每个实例都有自己的范围。两个指针都指向您分配的内存:

char *fData = malloc (length2 * sizeof (char));

..即使它们在代码执行时传入和传出范围。

答案 6 :(得分:1)

如果你没有释放你没有使用的内存,那么最终会累积 - 如果你用许多其他指针完成此操作 - 并且你的程序可能会耗尽内存。在使用free函数释放内存块之后,我还建议为指针分配NULL,因为这可以防止悬空指针,即使你已经释放指针,如果你尝试访问它,您可以获得未定义的行为,而NULL指针上的访问和操作会导致崩溃,因此您可以轻松地跟踪问题