给定这样一个函数声明:
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/