如何在引发异常时安全地处理数组指针

How to safely deal with an array pointer when throwing an exception

本文关键字:安全 处理 数组 指针 异常      更新时间:2023-10-16

当尝试C++方法封装C API时,我发现抛出异常时出现问题:

int status;
char* log = nullptr;
int infoLogLength;
getFooStatus(&status);
getFooLogLength(&infoLogLength);
if (!status) {
  log = new char[infoLogLength];
  getFooLog(infoLogLength, log);
  throw std::runtime_error(log);
}

我不允许以任何方式修改接口方法。

据我了解,我需要为要填充的方法保留内存,并对其进行操作。但是,抛出异常将从该方法返回,不允许我释放资源。我的代码是否正确,还是我应该以其他方式解决此问题?

>std:runtime_error期望一个std::string,所以给它一个std::string而不是一个char*

int status;
getFooStatus(&status);
if (!status) {
    int infoLogLength;
    getFooLogLength(&infoLogLength);
    std::string log(infoLogLength, '');
    getFooLog(infoLogLength, &log[0]);
    throw std::runtime_error(log);
}

或者,您可以传递一个 char* ,只需以促进自动释放的方式分配它,例如:

int status;
getFooStatus(&status);
if (!status) {
    int infoLogLength;
    getFooLogLength(&infoLogLength);
    std::vector<char> log(infoLogLength);
    getFooLog(infoLogLength, &log[0]);
    throw std::runtime_error(&log[0]);
}

我所知,runtime_error有两个重载,一个带有常量*字符,另一个是常量字符串&。

我相信构造一个 std::string 作为局部变量并将其传递给runtime_error应该会导致它被正确清理。

有一种简单的方法可以处理异常,而无需重构代码,以便数组由其析构函数清理的对象管理。即:

char* log = nullptr;
try {
  int status;
  int infoLogLength;
  getFooStatus(&status);
  getFooLogLength(&infoLogLength);
  if (!status) {
    log = new char[infoLogLength];
    getFooLog(infoLogLength, log);
    throw std::runtime_error(log);
  }
} catch (...) {  // special C++ syntax: "catch any exception"
  delete [] log;
  throw; // special C++ syntax: "re-throw" current exception
}

如果你只有一catch (...),看起来很像C++支持finallycatch (...)finally 功能之间的区别在于catch (...)不会无条件执行:它仅在没有更具体的catch时才执行。因此,如果要在同一try块中添加其他 catch 子句,它们都必须重复delete [] log清理操作。

这可以通过使用嵌套来缓解:

try {    // real exception-handling try
  try {   // try for unwind protection only
    ...
  } catch (...) {
    // clean-up statements
    throw;
  }
} catch (actual_error &err) {
  ...
} catch (another_exc_type &exc) {
  ...
}