2014-03-31 110 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) { 
    ... 
}