是的,两个讨厌的结构结合了。它听起来是否很糟糕,还是可以看作是控制goto使用并提供合理的清除策略的好方法?
在工作中,我们讨论了是否在我们的编码标准中允许goto。通常,没有人愿意允许免费使用goto,但是有些人对将其用于清除跳转表示肯定。如以下代码所示:
void func()
{
char* p1 = malloc(16);
if( !p1 )
goto cleanup;
char* p2 = malloc(16);
if( !p2 )
goto cleanup;
goto norm_cleanup;
err_cleanup:
if( p1 )
free(p1);
if( p2 )
free(p2);
norm_cleanup:
}
这种用法的明显好处是,您不必最终使用以下代码:
void func()
{
char* p1 = malloc(16);
if( !p1 ){
return;
}
char* p2 = malloc(16);
if( !p2 ){
free(p1);
return;
}
char* p3 = malloc(16);
if( !p3 ){
free(p1);
free(p2);
return;
}
}
尤其是在具有许多分配的类似构造函数的函数中,这有时会变得非常糟糕,尤其是当有人必须在中间插入某些内容时。
因此,为了能够使用goto,但仍然清楚地将其与自由使用隔离开来,创建了一组流控制宏来处理任务。看起来像这样(简化):
#define FAIL_SECTION_BEGIN int exit_code[GUID] = 0;
#define FAIL_SECTION_DO_EXIT_IF( cond, exitcode ) if(cond){exit_code[GUID] = exitcode; goto exit_label[GUID];}
#define FAIL_SECTION_ERROR_EXIT(code) exit_label[GUID]: if(exit_code[GUID]) int code = exit_code[GUID];else goto end_label[GUID]
#define FAIL_SECTION_END end_label[GUID]:
我们可以如下使用它:
int func()
{
char* p1 = NULL;
char* p2 = NULL;
char* p3 = NULL;
FAIL_SECTION_BEGIN
{
p1 = malloc(16);
FAIL_SECTION_DO_EXIT_IF( !p1, -1 );
p2 = malloc(16);
FAIL_SECTION_DO_EXIT_IF( !p2, -1 );
p3 = malloc(16);
FAIL_SECTION_DO_EXIT_IF( !p3, -1 );
}
FAIL_SECTION_ERROR_EXIT( code )
{
if( p3 )
free(p3);
if( p2 )
free(p2);
if( p1 )
free(p1);
return code;
}
FAIL_SECTION_END
return 0;
它看起来不错,但有很多好处,但是,在将其推广到开发之前,我们是否应该考虑任何缺点?毕竟,它非常易于控制和运行。两者都不鼓励。在这种情况下,劝阻他们的理由是什么?
谢谢。
最佳答案
错误处理是goto
不太糟糕的一种罕见情况。
但是,如果我必须维护该代码,我会很不高兴goto
被宏隐藏了。
因此,在这种情况下,goto
对我来说可以,但对宏来说不行。
关于c - 使用 'goto'的流控制宏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/700655/