是的,两个讨厌的结构结合了。它听起来是否很糟糕,还是可以看作是控制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/

10-13 08:32