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

C++临时对象内存释放异常:自定义字符串类运算符实现排查

问题分析与修复方案

你的核心问题出在**operator+=没有正确重新分配内存**,直接在原数组末尾写入超出容量的数据,导致堆内存损坏,后续临时对象析构时执行delete[]触发未定义行为(表现为阻塞)。另外代码里还有几个细节问题也需要修正,下面一步步解决:

1. 修复operator+=的内存分配逻辑

当前的operator+=直接把新字符串拷贝到p + this->size()的位置,但原数组的容量只有data_length + 1(存储原字符串加\0),根本没有空间容纳新内容,这会造成堆越界写入,破坏堆结构,最终导致析构时delete[]出错。

正确的实现应该:

  • 计算拼接后的总长度
  • 分配足够的新内存
  • 复制原字符串和要追加的字符串到新内存
  • 释放旧内存,更新指针和长度

修改后的operator+=:

Str& Str::operator+=(const Str &s) {
    // 计算新的总长度
    size_type new_length = data_length + s.data_length;
    // 分配新内存,+1是为了存储'\0'
    char* new_p = new char[new_length + 1];
    
    // 复制原字符串内容
    std::copy(p, p + data_length, new_p);
    // 复制要追加的字符串内容
    std::copy(s.p, s.p + s.data_length, new_p + data_length);
    // 添加字符串结束符
    new_p[new_length] = '\0';
    
    // 释放旧内存
    delete[] p;
    // 更新成员变量
    p = new_p;
    data_length = new_length;
    
    return *this;
}

2. 修正其他潜在问题

(1)默认构造函数初始化指针

默认构造函数里p没有初始化,会导致uncreate()里的delete[] p操作野指针,触发未定义行为。修改默认构造函数:

Str() : p(nullptr), data_length(0) {};

(2)修正end()方法的实现

原来的end()调用std::strlen(p),这不仅效率低(每次都要遍历字符串),还会在字符串包含\0时返回错误的长度。应该直接用data_length:

iterator end() { return p + data_length; }
const_iterator end() const { return p + data_length; }

(3)修正赋值运算符的参数

operator=(Str& rhs)的参数应该是const Str&,否则无法接收临时对象(比如operator+返回的临时对象),修改为:

Str& operator=(const Str& rhs)//assignment operator
{
    if (&rhs != this) {
        uncreate();
        create(rhs.size());
        std::copy(rhs.begin(), rhs.end(), p);
        p[data_length] = '\0';
    }
    return *this;
}

(4)完善uncreate()方法

确保uncreate()后p被置为nullptr,避免重复释放:

void Str::uncreate() {
    delete[] p;
    p = nullptr; // 置空指针
    data_length = 0;
}

3. 验证修复后的代码

修改后的完整代码可以正确执行字符串拼接,临时对象析构时也不会出现阻塞。测试你的main函数:

int main() {
    Str s1 = "hello";
    Str s2 = "worly";
    Str s3 = s1 + s2;
    // 可以添加输出验证:std::cout << s3.c_str() << std::endl;
    return 0;
}

额外说明

  • 你还可以实现移动构造函数和移动赋值运算符,提升operator+的效率(避免不必要的拷贝)。
  • 注意遵循三/五法则:因为你自定义了析构函数,必须正确实现拷贝构造、拷贝赋值,最好加上移动构造和移动赋值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:48:13