【问题标题】:Valgrind and ostream operatorValgrind 和 ostream 运算符
【发布时间】: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 &lt;&lt; 需要一个以空字符结尾的字符串。
  • 如果您不想在您的String 中使用以空值结尾的数据,您可以在您的operator&lt;&lt; 中使用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,然后在需要时分配更多内存,然后才继续阅读,是的- 但你可能很难找到合适的分隔符。

标签: c++ valgrind ostream


【解决方案1】:

如果我没有在任何地方使用过 strlen,为什么会在此处显示它?

return std::operator<<(os, other.str);

这与您执行此操作时调用的函数相同:

void foo(std::ostream& stream, const char * ptr) {
  stream << ptr;
}

如果不是通过strlen() 或类似的东西,流应该如何知道传递的以空结尾的字符串的长度?

【讨论】:

  • 我认为,在字符串文字的情况下,stream &lt;&lt; 会逐个字符地输出,直到达到 nul 终止符。这意味着它不需要调用strlen。你有任何证据证明strlen 被调用了吗? (只是好奇)
  • @ThomasMatthews,是的,这绝对是过于简单化了,我会更正答案
  • 一种技术是使用strlen,然后执行块写入。我在标准中没有看到任何关于如何实现 operator&lt;&lt; 的内容。
  • @ThomasMatthews 问题不在于标准,而在于 OP 看到的 strlen() 来自哪里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-10
  • 1970-01-01
  • 1970-01-01
  • 2017-04-13
  • 2013-10-10
  • 1970-01-01
  • 2018-03-31
相关资源
最近更新 更多