当前位置: 首页 > 知识库问答 >
问题:

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

彭炳
2023-03-14

对于下面的代码:(1)“main”调用函数“f1”。(2)函数“f1”进行一些数字运算;使用malloc创建一个“char”数组,然后将数组的指针返回到main(无需取消分配-free-数组)。

我有3个与此案例相关的问题:(1)我假设,虽然函数“f1”已经终止,但分配的char数组仍然保持分配状态,直到主程序完全终止。也就是说,分配的内存仍然属于main,没有其他进程可以从外部访问(我的意思是干扰)它。我说得对吗?(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);
}

共有3个答案

权胜泫
2023-03-14

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

一旦main成功终止,fdata指向的内存就会被释放。

所以,一旦不再需要内存,就释放内存被认为是好的。在程序结束时释放块是没有意义的,因为当进程终止时,程序的所有空间都会返回给系统(考虑到现代操作系统)。

龚鸿羽
2023-03-14

>

  • 是的,使用malloc()分配的内存会一直保留,直到它被释放。否则函数如何将可变大小的数据返回给其调用者?

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

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

    所有的C编程课程或教科书都应该涵盖这些内容。

  • 景才英
    2023-03-14

    我假设,尽管函数“f1”已经终止,但分配的char数组仍然保持分配状态,直到主程序完全终止。

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

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

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

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

    是的。在大多数系统中,当进程终止时,操作系统会自动释放未分配的内存,但这取决于系统。在我看来,即使操作系统这样做了,你也应该总是释放,使用这种自动释放作为危险信号(我忘记了释放,这是一个错误吗?我错过了什么?)。此外,如果f1被调用1000次,每次都会泄漏内存,很快吃掉所有可用内存。想想服务器中的一个进程,它可能(也应该)运行多年。

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

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

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

    请注意,如果您想隐藏此类内部指针,有很多技术。您可以使用令牌(例如整数、字典中的键)、typedef或不透明类型。

     类似资料:
    • 4. 分配内存的函数 除了malloc之外,C标准库还提供了另外两个在堆空间分配内存的函数,它们分配的内存同样由free释放。 #include <stdlib.h> void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); 返回值:成功返回所分配内存空间的首地址,出错返回NULL calloc

    • 我有一个func添加两个NO并返回(a+B)。然后我创建了一个指向func的func指针。希望为该函数指针的数组分配内存并访问它们。代码如下。 我的问题是使用malloc的下面一行: 编译时,sizeof(add_2nos*)和sizeof(add_2nos)没有任何区别。如果有什么区别??另外,如果类型转换是必要的,而我正在分配相同类型的内存…?

    • 问题内容: 对齐是的,没关系,但是对齐的呢?是否保留对齐方式或如何确保重新分配的内存具有相同的对齐方式?假设Linux和x86_64。 问题答案: 不,ISO或POSIX不能保证返回的内存保持相同的对齐方式。A 可以 简单地将当前块扩展到相同的地址,但也可以将其移动到对齐方式比原始地址严格的其他地址。 如果您想要相同的对齐方式,则最好分配另一个块并复制数据。 不幸的是,在单一UNIX规范中也没有任

    • 问题内容: 在Go中,如何将函数调用返回的值分配给指针? 考虑下面的示例,注意返回一个值(不是指针): 这些都失败了: 是否确实需要局部变量?那不会招致不必要的复制吗? 问题答案: 根据规范,必须使用局部变量。 要获取值的地址,调用函数必须将返回值复制到可寻址的内存中。有副本,但这不是多余的。 Go程序通常使用值。 有时在应用程序想要区分无值和其他时间值的情况下使用A。在SQL NULL和有效时间

    • 我正在尝试运行下面的程序,在该程序中,我使用一个名为Reserve的函数动态地为变量分配内存。当我运行应用程序时,由于在一个单独的函数中为一个空指针分配内存,我会得到分段错误,但是如果我想在主函数中分配内存,我不会得到这个错误。那我做错了什么? 代码如下:

    • DF: 我正在创建一个新的列“identify”,以查找(ID、日期)的分区,并通过“identify”选择排序最靠前的组合 预期DF: 代码1: 我的作品: 代码尝试2: 我的作品: 关于如何调整代码以获得所需OP的任何建议都将是有帮助的