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

修复MyStr类浅拷贝导致重复释放内存的访问违例问题

修复C++中重复释放内存导致的访问违规异常

这个问题的核心是浅拷贝带来的重复内存释放:你的拷贝构造函数直接把原对象的strPtr指针值复制给新对象,导致两个MyStr实例共享同一块堆内存。当程序结束时,foo和foo2先后调用析构函数,第一次delete已经把这块内存归还给系统,第二次delete操作已经失效的内存地址,自然就触发了读访问违规异常。

下面是保留原有逻辑前提下的修复代码:

#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
extern char MsgBuff[300];
class MyStr {
 string* strPtr;
public:
 // "normal" constructor
 MyStr(const string& str) : strPtr(new string(str)) {}
 // destructor
 ~MyStr() { 
     if(strPtr != nullptr) { // 用nullptr替代NULL,C++11及以上更规范
         delete strPtr;
         strPtr = nullptr; // 置空避免野指针,是良好编程习惯
     }
 }
 // 修复为深拷贝的拷贝构造函数
 MyStr(const MyStr& x) : strPtr(new string(*x.strPtr)) { 
     OutputDebugStringA("copy constructor"); 
 }
 // 修正输出信息的移动构造函数
 MyStr(MyStr&& x) : strPtr(x.strPtr) { 
     x.strPtr = nullptr; 
     OutputDebugStringA("move constructor"); // 原代码输出写错,修正为移动构造标识
 }
};
int main() {
 MyStr foo("Exam");
 MyStr foo2 = foo;
 return 0;
}

关键修改点说明:

  • 深拷贝拷贝构造函数:不再直接复制指针,而是通过new string(*x.strPtr)创建一块新的堆内存,把原对象字符串的内容完整复制进去。这样foo和foo2各自持有独立的内存块,析构时释放自己的内存,不会出现重复释放的冲突。
  • 修正移动构造函数的输出:原代码里移动构造函数错误输出了"copy constructor",改成"move constructor"后,调试时能准确区分是触发了拷贝还是移动操作。
  • 细节优化:把NULL换成C++11引入的nullptr,类型更安全;析构时释放内存后将指针置空,避免出现野指针(虽然对象销毁后这个指针不会再被使用,但这是值得保持的编程习惯)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 22:32:28