3

私は自分のバージョンの String クラスをコーディングしていますが、Valgrind<<は私の文字列に対する演算子の実装について不満を漏らしています。エラーは間違った行にあります.charごとに印刷するとうまくいきます.

どこが間違っていますか?

Valgrind エラー:

==2769== 条件付きジャンプまたは移動は、初期化されていない値に依存します

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

==2769== by 0x4ECAD60: std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*) (/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.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;
}
4

3 に答える 3

10

このような生の文字列を使用することはお勧めしません。

ただし、犯人はここにあります:

strncpy(_pData, inCString, _size+1);

または、代わりに、NUL終了文字を手動で保管します。

_pData[_size] = 0;

NUL終了文字が欠落しているため、出力操作は文字列の終わりを超えて実行され続けます。(コンパイラ、オプションなどによっては、文字が偶然にnulになる可能性があるため、動作は正常に見える場合があります。)

ヒント:

  • CAPIの代わりにC++スタイルを使用することを検討してください
  • Cスタイルを使用する必要がある場合は、char*少なくともstdrupfree
  • NULで終了する文字列を実行することを主張する場合は、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;
    }
    
于 2012-10-05T14:53:40.440 に答える
1

最後にゼロバイトを書き損じているからです。必要なもの:

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

バージョンの C 文字列関数については、すべて微妙に異なるセマンティクスを持っているため、マニュアルを常に注意深く読む必要があります。n

于 2012-10-05T14:56:04.660 に答える
-1

データ メンバーを明示的に初期化しているのではなく、値を割り当てていることに注意してください。

...初期化するには、次のように変更する必要があります。

String::String(const char* inCString) :
    _size(strlen(inCString)),
    _pData(new char[_size + 1])
{
    strncpy(_pData, inCString, _size);
}
于 2012-10-05T14:54:26.203 に答える