2016-09-03 34 views
3

那麼這裏是我的異常代碼:C++古怪的字符串/字符*異常行爲

class OptionNotFoundError: public std::exception { 
public: 
    OptionNotFoundError(std::string option, int position) throw() 
     : option(option), position(position) {} 
    OptionNotFoundError(char option_, int position) throw() 
     : position(position) { option.push_back(option_); } 

    virtual ~OptionNotFoundError() throw() {} 

    virtual const char* what() const throw() { 
     std::string what_str = "Option '" + option + "' not found in position " + std::to_string(position); 
     std::cout << what_str.c_str() << std::endl; 
     return what_str.c_str();; 
    } 

    std::string option; 
    int position; 
}; 

當異常被拋出,這裏是我的終點站下車:

terminate called after throwing an instance of 'Args::OptionNotFoundError' 
Option 'c' not found in position 1 
    what(): 

所以cout工作正常,但...不是回報。如果我使用return "smth"它工作正常。

怪異:如果我

std::string what_str = "test"; 

更換what_str定義我得到

terminate called after throwing an instance of 'Args::OptionNotFoundError' 
test 
    what(): x�zL� 

再次,cout<<工作正常。但是回報...並不是那麼多。這是一些編碼錯誤?

+0

有這個UB的重複噸... – dasblinkenlight

+2

考慮使用'std :: string what_str;''OptionNotFoundError'類的成員變量而不是'what()'函數內的局部變量。然後'what_str'仍然活着並踢,而不是在返回時被摧毀。 – PaulMcKenzie

回答

2

對於第一種情況,請注意what_strwhat()中的局部變量,它在退出函數作用域時將被銷燬,然後它返回的指針變爲懸空,解除引用會導致UB。

對於第二情況下,返回"smth"工作得很好,因爲"smth"const char[5],這是一個string literal

字符串文字具有靜態存儲持續時間,並且因此存在於內存中的程序的壽命。

對於第3的情況下,

如果我更換what_str定義與

std::string what_str = "test"; 

它不工作,因爲what_str仍然是一個本地std::string,問題是相同的與第一案件。

+0

......沒錯。起初,我寫了整個代碼內聯(沒有「臨時」字符串變量)(它並沒有更好的工作),所以我沒有想到char *指出的生命週期...... – Salamandar

+0

我把what_str移到了what()之外作爲該類,工作正常^^ – Salamandar

+0

@Salamandar是的這是一個有效的解決方案。請注意,對成員進行的任何更改都會使返回的指針無效,請注意。 – songyuanyao

4
return what_str.c_str();; 

c_str()指針返回到該std::string的內部內容。

該指針仍然有效,只是直到

  1. std::string對象被銷燬。

  2. std::string對象被修改。

從中獲取該c_str()指針時被摧毀了你的函數返回std::string對象。

這會導致未定義的行爲。您的函數返回的const char *不正確。它指向被摧毀對象的內部內容。