首页 文章

带有char *和<<运算符的条件跳转valgrind

提问于
浏览
3

我正在编写我的String类的版本,但Valgrind抱怨我的字符串 << 运算符的实现 . 错误是在错误的行,如果我通过char打印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(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;
}

3 回答

  • 1

    我不建议使用这样的原始字符串 .

    然而,罪魁祸首在这里:

    strncpy(_pData, inCString, _size+1);
    

    或者,也可以手动存储NUL终止字符:

    _pData[_size] = 0;
    

    通过缺少NUL终止字符,输出操作将继续运行超过字符串的结尾 . (行为可能看起来没问题,因为角色可能是偶然的,取决于编译器,选项等)

    暗示:

    • 考虑使用C风格而不是C API

    • 如果你必须使用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;
    }
    
  • -1

    因为您无法在结尾写入零字节 . 你需要:

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

    你应该非常谨慎地使用 n -反转C字符串函数,因为它们都有微妙的不同语义 .

  • 10

    请注意,您没有明确初始化数据成员,而是为它们分配值:

    ...为了初始化,你应该改为:

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

相关问题