使用 goto 作为错误处理策略
Using goto as a error handling strategy
我最近进行了一次代码审查,并开始了一场辩论。我的大部分代码如下所示:
for (i = 1; i <= 3; i++)
{
DoubleValue = tODBCX->getDouble(KeyFieldCount + i, IsNULL, IsSuccess);
if (IsNULL)
{
LoggerDrillHole::LogToDB(LOG_ERROR, L"Survey depth, dip and azimuth values can not be NULL.", __FUNCTIONW__);
IsSuccess = false;
goto EXIT;
}
else
{
if (i == 1)
Depth = DoubleValue;
else if(i == 2)
DipDegrees = DoubleValue;
else if (i == 3)
AzimuthDegrees = DoubleValue;
}
}
有争议的goto声明引发了争论。此代码包含在一个函数中,该函数通过初始化局部布尔变量 IsSuccess = true 开始生活,该函数最终返回 IsSuccess。EXIT 策略负责整理基本代码;
EXIT:
tODBCX->Close();
if (Key != 0) free(Key);
Key = 0;
if (PriorKey != 0) free(PriorKey);
PriorKey = 0;
return IsSuccess;
有几个这样的goto EXIT语句与设置IsSuccess = false和记录到数据库等相邻。有人评论说,这会破坏代码的流程。应该改用 do 循环(无限循环)并打破该循环,然后处理所有必需的,而不是使用 goto 语句。
我非常不喜欢无限循环策略,但如果它真的提高了可读性,我可以习惯它。有没有更好的方法?
将其标记为此问题的副本。尽管如此,它并不完全相同,即使解决方案是相同的:
在C++中,最好的解决方案是使用 RAII 和事务代码。在 C 中,最好的解决方案是使用 goto,并遵循一些规则(仅用于返回/清理,不要使用 goto 来模拟循环等)。
请参阅我在上面提到的问题中的回答(基本上,解决方案是使用 RAII 和事务代码);这将完全消除对 goto 清理/错误处理块的需求。
在这里使用goto
并没有错。这是为数不多的最干净解决方案的情况之一。(另一个例子是打破内部循环。
使用 do { ... } while (false)
循环是一种人工解决方案,实际上会降低代码的可读性。
在 C 中,考虑将代码分解为两个函数...一个外部函数,它执行常见的初始化并传递内部函数所需的变量,以便内部函数可以简单地返回成功状态,知道外部函数将清理。
在C++通常最好使用作用域防护,以便析构函数确保正确清理。 考虑您的:
tODBCX->Close();
如果tODBCX
需要比函数调用更长的寿命 - 因此析构函数中的Close()
没有帮助 - 则创建一个帮助程序:
struct Odbc_Access_Guard
{
Odbc_Access_Guard(ODBC& o) : odbc_(o) { }
~Odbc_Access_Guard() { odbc_.close(); }
operator ODBC&() { return odbc_; }
operator const ODBC&() const { return odbc_; }
ODBC& odbc_;
};
然后在函数内部:
Odbc_Access_Guard odbc(tODBC);
odbc.xyz();
if (whatever)
return ...success expression...;
同样的事情也适用于您的指针:它们可能应该是使用上述逻辑的共享指针或守卫。 然后,您可以随时返回,甚至不必考虑去哪里进行清理代码,也不必想知道它是否与当前的变量使用是最新的。
- 警告处理为错误这里有什么问题
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 处理多个异常集合的C++方法
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 使用流处理接收到的数据
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 基于多个条件处理地图中的所有元素
- 如何用数字处理log(0)
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- 错误处理.将系统错误代码映射到泛型
- 从文本文件中读取时钟时间和事件时间并进行处理
- 如何为多个文件处理选择最佳的I/O策略
- 在C++中使用异常的可能的错误处理策略是什么,它们的后果和影响是什么
- 使用 goto 作为错误处理策略
- 了解 Windows API 中消息处理的不同策略
- 您在软件中编写日志以处理可能大量的日志消息的策略是什么
- 处理请求的策略设计模式
- 不同的编译器用来处理数字转换中的溢出的常见策略是什么?
- C++实时策略模式来处理不同的数据