2016-03-30 123 views
0

我拋出一些解析異常。但一個例外需要破碎的字符串..?異常中的字符串損壞?

//Parse exception 
class ParseException : public exception { 
public: 
    //Constructor 
    //Arguments: 
    // Str: Message 
    // Pos: Position 
    ParseException(string Str, int Pos) { 
     msg = Str; 
     pos = Pos; 
    } 

    //Get what happened(From exception) 
    //Returns: 
    // Message with position 
    virtual const char* what() const throw() { 
     string str = msg; 
     str += " at " + to_string(pos); 
     return str.c_str(); 
    } 
private: 
    string msg; //Message 
    int pos; //Position 
}; 

這是異常類。我扔這個例外是這樣的:

throw ParseException("Mismatched bracket", P.Pos); 

,拋出此異常並進入:

try { 
    Parse(p); 
} 
catch (ParseException e) { // <<< Here 
    cerr << "ParseException: " << e.what() << endl; 
} 

而我得到的是:

ParseException: ▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌ 

有我的代碼有問題?或Visual Studio(或編譯器)的問題?

+3

'str'是'what()'的本地語言。當函數退出時它將被銷燬。返回'str.c_str()'產生未定義的行爲。 –

回答

3

As noted in the comments,您不能返回本地stringc_str而不會創建未定義的行爲。在異常本身上存儲what值的string緩存可能是有意義的; the char* returned by what needs to live as long as the exception object,所以緩存異常是合理的。

class ParseException : public exception { 
public: 
    //Constructor 
    //Arguments: 
    // Str: Message 
    // Pos: Position 
    ParseException(string Str, int Pos) : msg(std::move(Str)), pos(Pos) {} 

    //Get what happened(From exception) 
    //Returns: 
    // Message with position 
    virtual const char* what() const throw() { 
     // Lazily populate what so it's not populated until called 
     if (_what.empty()) { 
      _what = msg + " at " + to_string(pos); 
     } 
     return _what.c_str(); 
    } 
private: 
    string msg; //Message 
    int pos; //Position 
    string _what; 
}; 

另外,也計算在構造函數中的值,以便保持what兼容nothrow(匹配的C++標準庫例外)。