You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Valgrind检测自定义String类ostream重载代码时报错且出现strlen调用?

问题原因
  1. strlen的来源:你没有显式调用strlen,这个函数是标准库的std::operator<<(std::ostream&, const char*)内部调用的,该函数接收C风格字符串作为参数时,需要通过strlen计算字符串长度才能完成输出。
  2. Valgrind报错的根本原因:你的自定义String类构造函数存在问题:
    • 计算传入的C字符串长度得到size后,只给内部str指针分配了size字节的内存,没有预留1字节存储C风格字符串必需的\0终止符
    • 复制完字符后也没有手动追加\0终止符,导致str指向的内存不是合法的C风格字符串
    • 标准库函数拿到str指针后调用strlen扫描时,会超出你分配的内存范围读取,直到随机碰到内存里的\0才停止,因此触发了Valgrind的非法读报错。
  3. 额外问题:你构造函数里循环计算capacity的逻辑完全无效,size是提前计算好的固定值,循环内的判断不会得到正确的capacity,属于冗余逻辑。
修复方案

1. 修复const char*构造函数

分配内存时多申请1字节存储终止符,复制完内容后手动追加\0,同时修正capacity赋值逻辑:

// 修复后的const char*构造函数
String::String(const char* s) {
  size = 0;
  while(s[size] != '\0')
    ++size;
  // 多分配1字节存储终止符
  str = new char[size + 1];
  for (int i = 0; i < size; ++i) {
    str[i] = s[i];
  }
  // 手动追加字符串终止符
  str[size] = '\0';
  capacity = size;
}

2. (可选优化)重载ostream运算符的更安全实现

不依赖C风格字符串的终止符,直接用类内部存储的size输出对应长度的字符,不会触发额外的strlen调用,性能和安全性都更高:

// 修复后的ostream运算符重载
std::ostream &operator<<(std::ostream &os, const String& other) {
  return os.write(other.str, other.size);
}

修复完成后重新编译运行测试和Valgrind内存检测,报错就会消失,测试用例也能正常通过。

内容的提问来源于stack exchange,提问作者user16949111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 13:24:01