2016-03-30 124 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++标准库例外)。