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



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

我有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);
}

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

没错。动态分配的内存和函数无关,它属于进程。

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

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

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

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

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

当分配内存的人同时释放内存时,这很好。如果这不可能,那么调用者将负责这样的内存。例如,strdup()就是这样做的。在这种情况下,被调用的函数必须(以某种方式)返回一个指向已分配内存的指针(或另一个专用函数可以使用的句柄/令牌)。例如:

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

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

  1. 是的,使用malloc()分配的内存会一直保留到释放为止。否则,函数怎么可能向调用方返回可变大小的数据呢?

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

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

这一切都应该在任何C编程课程或教科书中涵盖。

malloc在堆上分配内存,因此该内存一直被分配,直到free函数释放或程序成功终止
在您的案例中,您在f1中释放了ftemp,因此在函数终止后它就不存在了。fdata仍在堆上,main可以访问它,因为您正在返回指向该分配位置的指针。

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

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

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

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

  3. 像这样:

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

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

这意味着你需要确保每个malloc都有相应的空闲,也并不意味着没有其他进程不能访问你的数据。它只是地址上的一个值。

在主存储器中,您必须free(fData)以避免内存泄漏。

综上所述:

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

2) 是的,您必须将其释放

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

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

读一点这两方面的内容会帮助你理解。我要指出的是,您有两个fData实例,每个实例都有自己的作用域。两个指针都指向您分配的内存:

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

即使它们在代码执行时传入和传出作用域。

如果你不释放你不使用的内存,最终这会累积起来——如果你用很多其他指针这样做的话——你的程序可能会耗尽内存。在使用free函数释放内存块后,我还建议将NULL分配给指针,因为这可以防止悬挂指针,因为即使你释放了指针,如果你尝试访问它,你也可能会得到未定义的行为,而对NULL指针的访问和操作会导致崩溃,所以你可以很容易地跟踪问题

相关内容

  • 没有找到相关文章