bugprone-empty-catch

检测并建议解决空 catch 语句的问题。

try {
  // Some code that can throw an exception
} catch(const std::exception&) {
}

在代码库中使用空 catch 语句可能是一个严重问题,开发人员应该意识到这一点。catch 语句用于处理程序执行期间抛出的异常。当抛出异常时,程序会跳转到与异常类型匹配的最近的 catch 语句。

空 catch 语句,也称为“吞掉”异常,会捕获异常,但不会对其进行任何处理。这意味着异常没有被正确处理,程序继续运行,就好像什么也没发生一样。这可能导致以下几个问题,例如

为了避免这些问题,开发人员应该始终正确处理异常。这意味着修复导致异常的根本问题或将异常向上传播到调用堆栈中更高层的处理程序。如果异常不重要,也应该以某种方式记录或报告它,以便可以跟踪和解决它。

如果异常可以在本地处理,则应该在 catch 块中处理它。这可能涉及记录异常或采取其他适当的措施以确保异常不会被忽略。

以下是一个例子

try {
  // Some code that can throw an exception
} catch (const std::exception& ex) {
  // Properly handle the exception, e.g.:
  std::cerr << "Exception caught: " << ex.what() << std::endl;
}

如果异常无法在本地处理,需要向上传播到调用堆栈,则应该重新抛出异常或抛出新的异常。

以下是一个例子

try {
  // Some code that can throw an exception
} catch (const std::exception& ex) {
  // Re-throw the exception
  throw;
}

在某些情况下,可能不需要在此级别捕获异常,可以将异常向上传播到调用堆栈。这可以通过简单地不使用 try/catch 块来实现。

以下是一个例子

void function() {
  // Some code that can throw an exception
}

void callerFunction() {
  try {
    function();
  } catch (const std::exception& ex) {
    // Handling exception on higher level
    std::cerr << "Exception caught: " << ex.what() << std::endl;
  }
}

避免空 catch 语句的另一种潜在解决方案是修改代码以避免首先抛出异常。这可以通过使用不同的 API、事先检查错误条件或以不涉及异常的不同方式处理错误来实现。通过消除对 try-catch 块的需求,代码变得更简单,更不容易出错。

以下是一个例子

// Old code:
try {
  mapContainer["Key"].callFunction();
} catch(const std::out_of_range&) {
}

// New code
if (auto it = mapContainer.find("Key"); it != mapContainer.end()) {
  it->second.callFunction();
}

总之,空 catch 语句是一种不良做法,可能导致隐藏的错误、安全问题、糟糕的代码质量和不可靠的代码。通过正确处理异常,开发人员可以确保其代码健壮、安全且可维护。

选项

IgnoreCatchWithKeywords

此选项可用于忽略包含某些关键字的特定 catch 语句。如果 catch 语句体包含(不区分大小写)此以分号分隔的选项中列出的任何关键字,则将忽略该 catch,不会发出警告。默认值:@TODO;@FIXME.

AllowEmptyCatchForExceptions

此选项可用于忽略特定异常类型的空 catch 语句。默认情况下,如果检测到空 catch 语句,无论捕获的异常类型如何,检查都会发出警告。但是,在某些情况下,例如当开发人员想要有意忽略某些异常或以其他方式处理它们时,可能希望允许特定异常类型的空 catch 语句。要配置此选项,应提供一个以分号分隔的异常类型名称列表。如果列表中的异常类型名称在空 catch 语句中被捕获,则不会发出警告。默认值:空字符串。