tal*_*lbi 1 c malloc free goto
我有以下代码:
void f(size_t n) {
int *a = malloc(n * sizeof *a);
if(a == NULL) {
report_error_and_exit();
}
int *b = malloc(n * sizeof *a);
if(b == NULL) {
free(a);
report_error_and_exit();
}
int *c = malloc(n * sizeof *a);
if(c == NULL) {
free(a);
free(b);
report_error_and_exit();
}
/*use a, b, c*/
}
Run Code Online (Sandbox Code Playgroud)
或类似的规定。基本上,我需要多个malloc,并且所有这些都不能失败。
我想知道我应该在哪里释放一些分配的内存。随着函数变得越来越长,检查malloc失败变得更加混乱。
我想到的一个可能的解决方案是执行如下操作:
void f(size_t n) {
int *a = malloc(n * sizeof *a);
if(a == NULL) {
goto malloc_fail;
}
/*...*/
malloc_fail:
free(a);
free(b);
/*...*/
report_error_and_exit();
}
Run Code Online (Sandbox Code Playgroud)
goto但是不鼓励使用。
我想知道对此的适当解决方案是什么。
goto这实际上是正确使用C 语言的经典示例。
虽然有可能滥用goto(而且严重滥用),但它确实有意义的情况之一是在像这样的错误处理代码中。它只是向前跳转,使代码更易于阅读,并将所有错误处理放在一处,这样就不容易出错。
然而,您必须注意的一件事是,如果您跳过变量的初始化,则该变量未初始化。鉴于您的示例,如果第一次调用malloc初始化a失败,那么当前编写的代码将调用free未b初始化c的代码。
这可以通过为每个故障设置不同的跳转目的地并以相反的顺序进行清理来解决。
void f(size_t n) {
int success = 0;
int *a = malloc(n * sizeof *a);
if(a == NULL) {
goto malloc_fail_a;
}
int *b = malloc(n * sizeof *b);
if(b == NULL) {
goto malloc_fail_b;
}
int *c = malloc(n * sizeof *c);
if(c == NULL) {
goto malloc_fail_c;
}
/*...*/
success = 1;
malloc_fail_c:
free(c);
malloc_fail_b:
free(b);
malloc_fail_a:
free(a);
if (!success) {
report_error_and_exit();
}
}
Run Code Online (Sandbox Code Playgroud)