2014-03-31 106 views
1

时,当试图封装C API在C++方法如何安全处理数组指针,我发现了一个问题抛出异常:抛出异常

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

如果这是C++,你为什么不使用字符串:

这可以通过使用嵌套得到缓解? –

+0

@RedAlert正如我所提到的,我被C api强制 - 我尝试使用字符串内部存储作为char数组,但无济于事。我可能会错过一些东西。 – kejran

回答

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]); 
} 
+0

谢谢。至于第一种方法,我得到了const char * - char * mismatch。我可以使用'&log [0]'而不是'log.data()'吗? – kejran

+0

是的,你可以使用'&log [0]'代替。 –

+1

@ user3483094:是的。这是自C++ 11以来的形式化。在C++ 03中,你正式不能依赖它,但它仍然适用于所有的实现。 – MSalters

0

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

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

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区块中添加其他捕获条款,则它们都必须重复清理操作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) { 
    ... 
}