【发布时间】:2021-12-16 11:12:55
【问题描述】:
为什么 Valgrind 在这段代码中显示错误?
// const char * constructor
String::String(const char* s) {
size = 0;
while(s[size] != '\0')
++size;
capacity = 0;
str = new char[size];
for (int i = 0; i < size; ++i) {
str[i] = s[i];
if (size > capacity && capacity == 0) {
++capacity;
} else if ((size > capacity && capacity != 0)) {
capacity *= 2;
}
}
}
// overloading the ostream operator
std::ostream &operator<<(std::ostream &os, const String& other) {
return std::operator<<(os, other.str);
}
// testing
TEST(Iostream, Out) {
std::stringstream os;
String s = "lol";
os << s;
ASSERT_EQ(os.str(), "lol");
}
// main function for testing
int main() {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
/////////////////////////////////////// //////////////// 如果我没有在任何地方使用过 strlen,为什么会显示在这里?
==11274== Invalid read of size 1
==11274== at 0x48425F4: strlen (vg_replace_strmem.c:469)
==11274== by 0x49BCBCD: std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28)
【问题讨论】:
-
您阅读
s直到空终止符,但您不复制空终止符本身。operator <<需要一个以空字符结尾的字符串。 -
如果您不想在您的
String中使用以空值结尾的数据,您可以在您的operator<<中使用os.write(other.str, other.size);。 -
注意构造函数中
capacity的计算是非常错误的。删除循环和if/else并设置capacity = size;。 -
@TedLyngmo for operator>> 我可以写 std::istream& operator>>(std::istream& is, String& obj) { is.read(obj.str, obj.size);回报是; } ?
-
@yash_21 您需要为从
istream读取的内容分配空间,因此,如果您向上阅读直到capacity,然后在需要时分配更多内存,然后才继续阅读,是的- 但你可能很难找到合适的分隔符。