抛出异常时如何安全地处理数组指针

时间:2014-03-31 23:43:07

标签: c++ exception

当尝试在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);
}

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

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

3 个答案:

答案 0 :(得分:2)

std:runtime_error需要std::string,因此请为std::string代替char*

int status;
getFooStatus(&status);

if (!status) {
    int infoLogLength;
    getFooLogLength(&infoLogLength);
    std::string log(infoLogLength, '\0');
    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]);
}

答案 1 :(得分:0)

据我所知,runtime_error有两个重载,一个带有const * char,另一个带有const string&amp;。

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

答案 2 :(得分:0)

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

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) {
  ...
}