当尝试在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);
}
我不允许以任何方式修改接口方法。
据我所知,我需要为填充方法保留内存,并对其进行操作。但是,抛出异常将从方法返回,而不是让我释放资源。我的代码是否正确,还是应该以其他方式解决这个问题?
答案 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 ++支持finally
。 catch (...)
和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) {
...
}