2016-07-05 92 views
1

這個問題已得到部分回答:解決方法是在我的課程的一個領域,特別是_escape,有UB。但是,Visual Studio的堆棧跟蹤爲什麼不顯示運算符函數,調試器是否也能找到它 - 這幾乎就像是有一種優化(我禁用了優化)來移除符號並將其與打印函數合併在一起。覆蓋<<(stream)運算符時,調試會轉換爲std的<< impl而不是?

我已經知道

我看到所有的熱門帖子上SO約< <運算符重載。我遵循了所有的基本語義。這不是任何熱門帖子的重複問題。

要覆蓋< <操作,需要定義一個函數的一般格式爲:我已經在我的程序這樣做

ostream& operator<<(ostream& os, const MyObject& dt) 

我使用Microsoft Visual Studio 2015年對於這個項目,並使用調試器嘗試進入運算符功能< <。但是,從來沒有,我定義爲函數內得到如下:

std::ostream& operator <<(std::ostream& os, const EscapeStr& t) 
{ 
    t.print(os); 
    return os; 
} 

其中EscapeStr是我用下面的函數定義定義print類:

void print(std::ostream& os) const { 
    for (int i = 0; i < _elem.length(); i++) { 
     char c = _elem[i]; 
     if (_delim[c]) { 
      for (int j = 0; j < _escLen; j++) { 
       os << _escape[j]; 
      } 
     } 
     os << _elem[i]; 
    } 
} 

問題

我看到使用VS調試器在這裏調用了print()函數,但我無法觀察到進入我重寫的範圍的程序,而是進入的std定義<,具有以下特徵:

template<class _Traits> inline 
    basic_ostream<char, _Traits>& operator<<(
     basic_ostream<char, _Traits>& _Ostr, 
     const char *_Val); // insert NTBS into char stream 

這是非常奇怪的,因爲只有ostream的覆蓋運營商可以訪問我目前公共職能。 Visual Studio只是在說謊嗎?

我不明白這是怎麼回事,我的其他重載之一,做的工作,並且簽名甚至不是準確(不常量和參考):

/// ostream operator for indent 
std::ostream& operator <<(std::ostream &os, indent x) 
{ 
    static const std::string spaces(" "); 
    while(x.d--) { 
     os << spaces; 
    } 
    return os; 
} 

結果,我程序正在展示一些UB(閱讀std庫代碼會讓我瘋狂)。這是一個顯示UB的人:https://ideone.com/jxro5s。任何幫助將不勝感激。

爲MVCE和清晰度

const static char _delims[] = { '\\', '"' }; 
const static std::vector<char> delims(_delims, _delims + 2); 

class EscapeStr { 
    const static unsigned short MAX_CHAR = 256; 

    std::string &_elem; 
    bool _delim[MAX_CHAR]; 
    const char* _escape; 
    int _escLen; 
public: 
    EscapeStr(std::string &elem, 
     const std::vector<char> &delim = std::vector<char>(1, '"'), 
     const std::string &escape = "\\") : 
     _elem(elem), 
     _escape(escape.c_str()), 
     _escLen(escape.size()) 
    { 
     for (int i = 0; i < MAX_CHAR; i++) { 
      _delim[i] = false; 
     } 
     for (int i = 0; i < delim.size(); i++) { 
      _delim[delim[i]] = true; 
     } 
    } 
    void print(std::ostream& os) const { 
     for (int i = 0; i < _elem.length(); i++) { 
      char c = _elem[i]; 
      if (_delim[c]) { 
       for (int j = 0; j < _escLen; j++) { 
        os << _escape[j]; 
       } 
      } 
      os << _elem[i]; 
     } 
    } 
}; 

這裏的額外信息是堆棧跟蹤的圖像 - 沒有< <運營商的標誌。 enter image description here

編輯:爲了預測未來的評論/關於我不使用std :: quoted的帖子 - 我試圖讓程序與低於C++ 11的版本兼容。

+0

如果調用'print()',那麼你的覆蓋的'operator <<'被調用嗎?另外,你的'operator <<'應該聲明爲'const'。 – ArchbishopOfBanterbury

+0

看起來你的類有一個cast操作符,它被調用來將'EscapeStr'轉換爲'char const *'。這很可能是你的'operaro <<'函數在你調用它的時候沒有聲明。 –

+0

@ArchbishopOfBanterbury我會這麼想,但是我在該運算符的每一行上都放了斷點,並且它從未插入。 – OneRaynyDay

回答

3

我認爲要做的第一件事是修復在點被銷燬的臨時字符串後,從_escape讀取的未定義行爲。我腦海中最好的選擇是用std::string escape_;替換const char* _escape; int _escLen;,然後你的for循環變爲os << escape_;。既然我們在這裏談論UB,任何事情都可能發生,包括不叫你的自定義operator<<

+0

啊 - 你說得對。我忽略了那個錯誤,因爲我非常專注於試圖讓'operator <<'工作。我會解決這個問題並報告任何結果。謝謝你的收穫! 編輯:修正,但我仍然無法看到運營商<<進入我的功能。但是,產量如預期。這可能是視覺工作室的問題嗎?我會暫時拋開這個問題來鼓勵一些關於visual studio調試器的討論,但是我可能會接受你的答案,因爲它解決了我的輸出問題。 – OneRaynyDay

相關問題