C如何释放malloc';当程序遇到错误并在不同的地方退出时,内存会被删除吗?

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);

我正在努力找到一种干净的方法来处理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);
  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那么,您能否告诉我,在函数退出后,以这种方式分配的内存是否会释放?我只是好奇-我一直认为它会在堆栈上分配空间,然后释放它。在某种程度上是的,程序退出后,堆栈将恢复到以前的状态,因此内存有效地被释放