c - 发生错误时如何释放先前分配的内存?

标签 c memory-management error-handling

给定这样一个函数声明:

int base_address(zval *object, int add_prefix, char **base_address TSRMLS_DC) {    
    int result;

    char *host;
    long port;
    char *prefix;  

    host = ... get host from object ...;
    port = ... get port from object ...;
    prefix = ... get prefix from object ...;

    result = SUCCESS;

    if (asprintf(base_address, "%s:%ld/%s", host, port, prefix) < 0) {
        result = FAILURE;
    }

    return result;
}

void my_func() {
    char *base_address;
    char *ping_url;

    if (base_address(getThis(), 0, &base_address TSRMLS_CC) == FAILURE) {
        MALLOC_ERROR();
    }

    if (asprintf(&ping_url, "%s/ping", base_address) < 0) {
        MALLOC_ERROR();
    }

   ... do some stuff with base address ...

    // release both, as everything worked
    free(base_address);
    free(ping_url);
}

如果第一次调用 base_address 成功而第二次调用 asprintf() 失败,我该如何干净利落地跳到函数末尾以安全释放分配的内存?

在没有太多代码重复或 goto 语句的情况下一个接一个地分配内存(并且每次分配都可能失败)的情况下,是否有一些标准模式如何避免内存泄漏?

最佳答案

不要害怕 goto。这是在 C 语言中处理异常的最简单、最干净、最易读的方式:

  • 您不会重复自己。重复的代码很容易出错。

  • 您不会创建深度嵌套的代码。深度嵌套难以辨认。

  • 您不会躲在 do {...} while (0)break 后面。好的代码说明了它的含义。

这是一个基本的例子:

int operation() {

    int result = SUCCESS;

    if ((result = may_fail_first()) == FAILURE) {
        goto failed_first;
    }

    if ((result = may_fail_second()) == FAILURE) {
        goto failed_second;
    }

    // If your cleanup code doesn't ordinarily need to run.
    goto end;

failed_second:
    cleanup_second();

    // If you don't need to clean up everything.
    goto end;

failed_first:
    cleanup_first();

end:
    return result;

}

关于c - 发生错误时如何释放先前分配的内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7491441/

相关文章:

关闭文件描述符

c - 尝试访问 C 中释放的内存时没有警告

asp.net - 我们可以记录 Bundle 错误吗?

actionscript-3 - AS3-addChild错误#1009-IOErrorEvent.IO_ERROR

c - 使用没有调试符号的 GDB

无法遍历C链表

c++ - _CrtSetAllocHook - 未处理的异常

c++ - 为数据库实现 block 存储

iphone - 如果我收到内存警告,在哪里发布我的所有观点?

asp.net - 遵循教程后的ASP.Net警告和错误-需要帮助