【问题标题】:Right way to handle errors and free memory in C在 C 中处理错误和释放内存的正确方法
【发布时间】:2015-05-04 07:14:33
【问题描述】:

在某些函数中,我需要使用 malloc() 分配内存并有几个 if..else 语句,如伪代码所示:

allocate memory
if condition_1
    do_stuff
    if condition_2
        do_more_stuff
    else
        error
else
    error
free allocated memory
return

所以我在开始时分配内存,如果一切正常,它就会被释放。但目前错误函数只打印错误消息并退出程序。但是正如我经常读到的那样,尽管当程序退出并且操作系统处理通常会处理之后的释放时,它不会释放内存,但它不是很好的风格。我怎样才能以懒惰的方式释放钱?我是否必须编写一个错误函数,将每个指针指向我分配的必须释放的内存,指针可能是不同的数据类型?或者我应该在调用错误函数之前放 free(ptr) 吗?一个错误函数,它接受一个数据类型为 void 的指针数组,并且比所有的都释放,会这样做吗?

【问题讨论】:

  • 如果你在错误处理之前调用free(ptr),你肯定会释放ptr。只是一种简单直接的方法。
  • 这里没有偷懒的方式。最懒惰的方法是编写函数error 来处理错误并释放内存。
  • 您也可以编写自己的分配包装器来跟踪所有分配的指针,然后循环它们并释放它们,但它当然会有一些开销..
  • 从多个错误点释放资源的常用方法是goto cleanup
  • @black:目前最好的答案。这正是它在 Linux 内核中的完成方式,尽管使用 goto 经常被批评为不好的做法,但我想说对于 C 中的错误处理,这是一个最佳做法。使代码更加紧凑和可读。

标签: c memory error-handling malloc


【解决方案1】:

我有两个解决方案。

您可以在调用free 和error 的位置添加标签:

void function(void)
{
    Memory *p = malloc(sizeof(*p));
    if (condition_1) {
        do_stuff();
        if (condition_2) {
            do_more_stuff();
        } else {
            goto err;
        }
    } else {
        goto err;
    }
    free(p);
    return;
err:
    free(p);
    error();
}

您也可以使用标志来标记错误:

void function(void)
{
    Memory *p = malloc(sizeof(*p));
    bool err = false;
    if (condition_1) {
        do_stuff();
        if (condition_2) {
            do_more_stuff();
        } else {
            err = true;
        }
    } else {
        err = true;
    }
    free(p);
    if (err)
        error();
}

我认为第二种解决方案在这种情况下看起来最好,但它们都同样有效。

【讨论】:

  • 谢谢,第二个看起来不错,但就我而言,我必须先中止,因为在 if..else 语句之后我有更多代码,所以第一个解决方案对我有用。但我也喜欢第二个。 :-)
【解决方案2】:

不要使用 goto。使用一次性while。此外,如果您需要错误标志,请将其默认为 true 而不是 false 以保存代码:

...malloc...
err = 1;
do {
    ...
    if <condition> break;
    ...
    if <condition> break;
    ...
    if <condition> break;
    ...
    err = 0;
} while (0);
...free...
if (err) ...

【讨论】:

    【解决方案3】:

    据我了解,您关心在因错误退出程序时释放所有内存,但不想手动处理所有指针。

    这里有个有趣的想法,写一个函数allocMemory,它返回malloc的结果,同时把指针放入链表,然后freeMemory把它从链表中删除,最后释放所有遍历链表并释放的函数所有的指针。 使用 allocMemory 和 freeMemory 函数代替 malloc 和 free,并在出错时调用 freeMemory 函数。

    【讨论】:

    • 好吧,听起来很有趣,我想我会尝试这种方式。 :-)
    猜你喜欢
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 2017-03-20
    • 2023-03-11
    • 2012-07-20
    相关资源
    最近更新 更多