对于以下代码:(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
或不透明类型。
-
是的,使用
malloc()
分配的内存会一直保留到释放为止。否则,函数怎么可能向调用方返回可变大小的数据呢? -
当程序退出时,它用
malloc()
分配的所有内存都将被释放。然而,在程序终止之前保留大量不需要的内存通常不是一个好主意,因为这可能会影响性能,或者系统可能会耗尽虚拟内存。对于长时间运行的程序来说,这可能是一个特别的问题,它们的内存使用量有时会不断增长,直到它们使用了所有可用的虚拟内存。 -
您可以对函数返回的指针调用
free()
。因此,在您的情况下,main()
可以在使用数组完成free(fData)
。
这一切都应该在任何C编程课程或教科书中涵盖。
malloc
在堆上分配内存,因此该内存一直被分配,直到free
函数释放或程序成功终止
在您的案例中,您在f1
中释放了ftemp
,因此在函数终止后它就不存在了。fdata
仍在堆上,main
可以访问它,因为您正在返回指向该分配位置的指针。
一旦main
成功终止,fdata
指向的内存将被释放。
因此,一旦你不再需要内存,就释放内存被认为是件好事。在程序结束时释放块是没有意义的,因为当进程终止时(考虑到现代操作系统),程序的所有空间都会还给系统。
-
是的,它还在堆里。然而,您对过程的概念感到困惑。除非您创建另一个进程(在*nix上使用
fork
),否则它仍然是同一个进程。 -
在不使用内存时释放内存是个好习惯。但是,如果程序正常终止,分配的内存将由系统释放。
-
像这样:
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
指针的访问和操作会导致崩溃,所以你可以很容易地跟踪问题