2012-10-05 49 views
3

我正在編寫我的版本的字符串類,但Valgrind抱怨我的我的字符串執行<<運算符。錯誤是在錯誤的行,如果我打印字符char它工程很好。條件跳轉valgrind與char *和<<運算符

我在哪裏錯了?

Valgrind的錯誤:

==2769== Conditional jump or move depends on uninitialised value(s)

==2769== at 0x4C2AC28: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)

==2769== by 0x4ECAD60: std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)

==2769== by 0x400BD5: operator<<(std::ostream&, String&) (string.cpp:22)

==2769== by 0x400AAC: main (main.cpp:12)

<<操作字符串:

ostream & operator << (ostream & o, String & inS) { 
    o << inS._pData << " "; // the wrong line 
    return o; 
} 

String類:

class String { 
    public: 
     unsigned _size; 
     char * _pData; 
     String(); 
     String(const char* inCString); 
}; 

構造函數(用於char*):

String::String(const char* inCString) { 
    _size = strlen(inCString); 
    _pData = new char[_size + 1]; 
    strncpy(_pData, inCString, _size); 
} 

Main.cpp的:

int main(int, char**) { 
    String s1("hello"); 
    cout << s1; 
    return 0; 
} 
+2

請問爲什麼你要重新實現字符串的麻煩? – Benj

+0

你是否遵守[Rule of Three](http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming))? –

+0

@MooingDuck:是的,但不是整個代碼在這裏;只有相關的。 – bagage

回答

10

我不建議使用這樣的原始字符串。

然而,罪魁禍首是在這裏:

strncpy(_pData, inCString, _size+1); 

,或者,手動存儲NUL終止字符:

_pData[_size] = 0; 

通過缺失NUL終止字符,則輸出操作只要繼續跑過字符串的末尾。 (該行爲可能發生在一下行不行,因爲字符可能是偶然被NUL,這取決於編譯器選項等)

提示:

  • 考慮使用C++風格而不是C API的
  • 如果你必須使用 C風格char*,至少使用stdrupfree
  • ,如果你堅持做NULL結尾的字符串,考慮編寫的C++太方式:

    #include <iostream> 
    #include <vector> 
    
    class String 
    { 
    public: 
        std::vector<char> _data; 
        String(); 
        String(const char* inCString); 
    }; 
    
    std::ostream & operator << (std::ostream & o, String const& inS) 
    { 
        o.write(inS._data.data(), inS._data.size()); 
        return o << ' '; 
    } 
    
    String::String(const char* inCString) 
    { 
        for (const char* it=inCString; it && *it; ++it) 
         _data.push_back(*it); 
    } 
    
    int main(int, char**) 
    { 
        String s1("hello"); 
        std::cout << s1; 
        return 0; 
    } 
    
+1

@cqnqrd你也應該小心初始化'_pData'空(null-terminated )在你的構造函數中沒有參數的字符串 – penelope

+1

事實上,我必須使用char *(student),但感謝您的建議,我會練習它們。 – bagage

-1

注意,你是不是明確的初始化數據成員,你將值分配給他們:爲了初始化

...,你應該更改爲:

String::String(const char* inCString) : 
    _size(strlen(inCString)), 
    _pData(new char[_size + 1]) 
{ 
    strncpy(_pData, inCString, _size); 
} 
+0

這與OP的問題無關。 –

+2

@penelope:不,他們不是。整數和指針不會被初始化,除非明確構造,la'C :: C():m_size(),m_ptr(){}'。 – xtofl

+0

@penelope,它們是POD類型,所以不調用默認的構造函數。 _size值未定義,_pData指向垃圾。 –

1

因爲您未能在最後寫入零字節。您需要:

strncpy(_pData, inCString, _size + 1); 
//        ^^^^ 

你應該總是read the manual非常仔細地與n -versions的C字符串函數,因爲它們都有着微妙的不同語義。

+0

噢好吧,我也需要複製它。感謝您的建議,我現在會仔細地做。 – bagage