C如何释放malloc';当程序遇到错误并在不同的地方退出时,内存会被删除吗?
我正在努力找到一种干净的方法来处理C语言中分配的内存。假设我有这样的东西:C如何释放malloc';当程序遇到错误并在不同的地方退出时,内存会被删除吗?,c,memory-management,malloc,free,C,Memory Management,Malloc,Free,我正在努力找到一种干净的方法来处理C语言中分配的内存。假设我有这样的东西: void function(int arg) { char *foo; foo = (char *)malloc(sizeof(char) * 100); int i = func1(arg, &foo); char *bar; bar = (char *)malloc(sizeof(char) * 100); int j = func2(&bar); free(foo);
void function(int arg) {
char *foo;
foo = (char *)malloc(sizeof(char) * 100);
int i = func1(arg, &foo);
char *bar;
bar = (char *)malloc(sizeof(char) * 100);
int j = func2(&bar);
free(foo);
free(bar);
}
我的问题是func1
和func2
可能会遇到错误并退出(1),因此发生这种情况时,我需要释放foo
和bar
如果func1
遇到错误,我只要调用free(foo)
就可以了。但是如果func2
遇到错误,我不能直接调用free(bar)
,因为我还需要释放foo
。这会变得非常复杂,我觉得这不是处理记忆的正确方法
我有什么遗漏吗?如果有人能给我指出正确的方向,那就太棒了。谢谢 一种处理方法:
void function() {
int size = 100;
char bar[size];
char foo[size];
// do stuff
//compiler frees bar and foo for you
}
如果在某些情况下func1()
或func2()
将调用exit(1)
,则无需担心释放foo
或bar
的内存,因为一旦进程退出,操作系统通常会进行清理
只要您在正常执行过程中在正确的时间(在退出
函数之前)释放,就没有内存泄漏。如果函数调用退出
,您根本不需要清理内存使用情况,操作系统将释放内存。但是,如果您需要释放其他资源(例如,锁定文件、清理临时文件等),那么您可以使用该函数,或者如果您使用gnu libc函数,则可以使用该函数来完成此工作。我认为可以用一种简单的方法来解决此问题
在分配资源时,只需在整个程序中维护一个allocCode,如下所示。
要记住的关键点很少。首先,不要在您的switch case中中断
语句。每次成功分配资源时,递增allocCode。对于添加的每个资源,您应该在顶部的交换机中添加一个案例,并增加一个数字。因此,调用函数freeResourceBeforeExit()
将以正确的顺序释放所有资源。请记住,由于没有中断,开关盒将在正确的位置进入,并释放其入口点以下的所有资源
我将编写psuedo代码
int allocCode = 0;
int freeResourceBeforeExit()
{
switch(allocCode)
{
case 4:
free(resource3);
case 3:
free(resource2);
case 2:
free(resource1);
case 1:
free(resource0);
}
exit(0);
}
int main()
{
...
resource0 = malloc(10);
allocCode++;
func1();
...
resource1 = malloc(100);
allocCode++;
func2();
...
resource2 = malloc(1000);
allocCode++;
...
func3();
...
resource3 = malloc(10000);
allocCode++;
func4();
...
so on..
}
希望这有帮助 如果你把工作分成几个部分,管理资源就会容易得多
void part1(int arg) {
char *foo;
foo = (char *)malloc(sizeof(char) * 100);
int i = func1(arg, &foo);
free(foo);
}
void part2(void) {
char *bar;
bar = (char *)malloc(sizeof(char) * 100);
int j = func2(&bar);
free(bar);
}
void function(int arg) {
part1(arg);
part2();
}
现在,如果需要,每个部件都可以在退出之前释放其参数。原则上,您可以安装一个带有atexit
的处理程序,该处理程序知道如何释放缓冲区。处理程序将作为调用func1
的结果被调用exit
。使用起来不是很愉快——处理程序不接受任何参数,这意味着您需要使用全局变量(或局部静态变量)来存储需要释放的内容。它不能被注销,这意味着您需要将这些全局变量设置为null(或其他一些特殊值),以表明您自己已经释放了资源,但仍将调用该处理程序。通常,您会使用atexit
处理程序作为挂起自己的资源清理框架的“钩子”
实际上,对于几个malloc
ed缓冲区来说,这通常太麻烦了,因为当程序退出时,功能齐全的操作系统在任何情况下都会释放进程保留的所有内存
在退出之前释放内存甚至可能代价高昂-为了用free
释放每个分配,内存将被触摸,这意味着它需要从主存甚至从交换拖到缓存中。对于大量可能需要一段时间的小型分配。当操作系统为您执行此操作时,它只是取消映射进程的内存映射,并开始在将来重新使用该地址空间/内存/交换空间进行其他操作。清理有好处(例如,它使代码更易于重用,使真正的泄漏更容易发现),但也有成本
顺便说一句,函数func1
在出错时调用exit
,这是相当反社会的,因为正如您所发现的那样,它限制了函数的用户。尽管func1
失败,但即使他们认为自己的程序可以/应该继续运行,他们也无法恢复func1实际上已经声明,这对于程序来说太重要了,甚至不能梦想在没有结果的情况下继续下去。是的,GMP,我是指你。如果他们正在做exit(1)
,那么你不需要释放任何东西-当流程被破坏时,系统会为你这样做。通常(不是在这种情况下)在获取资源的情况下编写系统C。正确。你不应该在退出前释放。但是,一般来说,使用随机函数exit(1)
不是一个好主意,因为它会抑制代码重用。@Willpamer那么有什么比exit(1)
更好的方法呢?我是否应该返回类似-1的值来表示错误,并在主函数中处理它?@iBlue:您的泄漏检测软件会将其报告为一种内存泄漏。因此,即使它在生产代码中无害,也有一些动机在可能的情况下进行清理,以防止虚假警告掩盖任何真正的内存泄漏。实际上,您更关心另一种泄漏:当程序仍在运行时,无法访问的未折叠块比程序退出时的未折叠块要糟糕得多。编译器在这段代码中肯定100%不会调用free
。Ok不调用free
,但会释放内存,否?@KerrekSB那么,您能否告诉我,在函数退出后,以这种方式分配的内存是否会释放?我只是好奇-我一直认为它会在堆栈上分配空间,然后释放它。在某种程度上是的,程序退出后,堆栈将恢复到以前的状态,因此内存有效地被释放