我试图用C编写一个函数来解决数学问题。在该函数中,有几个步骤,每个步骤都需要分配一些内存,其大小取决于前面步骤中的计算结果(因此,我不能在函数开始时全部分配它们)。伪代码如下所示:
int func(){
int *p1, *p2, *p3, *p4;
...
p1 = malloc(...);
if(!p1){
return -1; //fail in step 1
}
...
p2 = malloc(...);
if(!p2){
free(p1);
return -2; //fail in step 2
}
...
p3 = malloc(...);
if(!p3){
free(p1);
free(p2);
return -3; //fail in step 3
}
...
p4 = malloc(...);
if(!p4){
free(p1);
free(p2);
free(p3); /* I have to write too many "free"s here! */
return -4; //fail in step 4
}
...
free(p1);
free(p2);
free(p3);
free(p4);
return 0; //normal exit
}
上述处理malloc故障的方法非常丑陋。因此,我通过以下方式进行操作:
int func(){
int *p1=NULL, *p2=NULL, *p3=NULL, *p4=NULL;
int retCode=0;
...
/* other "malloc"s and "if" blocks here */
...
p3 = malloc(...);
if(!p3){
retCode = -3; //fail in step 3
goto FREE_ALL_EXIT;
}
...
p4 = malloc(...);
if(!p4){
retCode = -4; //fail in step 4
goto FREE_ALL_EXIT;
}
...
FREE_ALL_EXIT:
free(p1);
free(p2);
free(p3);
free(p4);
return retCode; //normal exit
}
尽管我认为现在它更加简洁,清晰和美观,但我的队友仍然强烈反对使用“goto”。他提出了以下方法:
int func(){
int *p1=NULL, *p2=NULL, *p3=NULL, *p4=NULL;
int retCode=0;
...
do{
/* other "malloc"s and "if" blocks here */
p4 = malloc(...);
if(!p4){
retCode = -4; //fail in step 4
break;
}
...
}while(0);
free(p1);
free(p2);
free(p3);
free(p4);
return retCode; //normal exit
}
嗯,这似乎是避免使用'goto'的一种方法,但是这种方法会增加缩进量,从而使代码难看。
所以我的问题是,还有其他方法可以以良好的代码风格处理许多“malloc”失败吗?谢谢你们。
最佳答案
询问您的队友他将如何重新编写这种代码:
if (!grabResource1()) goto res1failed;
if (!grabResource2()) goto res2failed;
if (!grabResource3()) goto res3failed;
(do stuff)
res3failed:
releaseResource2();
res2failed:
releaseResource1();
res1failed:
return;
并询问他如何将其推广到
n
资源。 (在这里,“获取资源”可能意味着锁定互斥锁,打开文件,分配内存等。“NULL上的释放就可以了”黑客无法解决所有问题……)在这里,
goto
的替代方法是创建一个嵌套函数链:抢占资源,调用一个获取另一个资源的函数,然后调用另一个获取资源并调用另一个函数的函数...当一个函数失败时,其调用者可以释放它的资源和返回失败,因此释放在堆栈展开时发生。但是您真的认为这比gotos容易阅读吗?(此外:C++具有构造函数,析构函数和RAII惯用语来处理这类事情。但是在C语言中,这是
goto
显然是正确答案的一种情况,IMO。)关于c - 还有其他方法可以处理许多 'malloc'故障吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6755934/