在析构函数中删除指针时崩溃
Crash When Deleting Pointer in Destructor
我遇到了对C++中的指针缺乏深入理解的问题。我写了一个名为Skymap的类,它有以下定义:
class Skymap {
public:
Skymap();
~Skymap();
void DrawAitoffSkymap();
private:
TCanvas mCanvas;
TBox* mSkymapBorderBox;
};
其功能定义为:
#include "Skymap.h"
Skymap::Skymap()
{
mCanvas.SetCanvasSize(1200,800);
mMarkerType=1;
}
Skymap::~Skymap()
{
delete mSkymapBorderBox;
}
void Skymap::DrawAitoffSkymap()
{
TBox* mSkymapBorderBox=new TBox(-200,-100,200,100);
//Use the mSkymapBorderBox pointer for a while
}
(我使用的是ROOT绘图包,但我认为这只是一个通用的C++问题)。
现在,以下程序将在到达skymap2的析构函数时崩溃:
int main(){
Skymap skymap1;
Skymap skymap2;
skymap1.DrawAitoffSkymap();
skymap2.DrawAitoffSkymap();
return(0);
}
但是,以下不会崩溃:
int main(){
Skymap skymap1;
skymap1.DrawAitoffSkymap();
return(0);
}
此外,如果我在构造函数中将指针mSkymapBorderBox初始化为NULL,那么在执行第一个程序(有2个Skymap对象)后,我将不再遇到崩溃。
有人能解释一下造成这种情况的根本原因吗?第二个Skymap对象中的指针似乎有问题,但我不知道它是什么。
TBox* mSkymapBorderBox=new TBox(-200,-100,200,100);
在这里,您将内存分配给一个局部变量,而不是成员变量。由于您没有为成员变量分配内存,因此对其调用delete
将调用未定义的行为,这将导致您的情况下崩溃。
你应该做的是:
mSkymapBorderBox=new TBox(-200,-100,200,100);
它现在为成员变量分配内存。这也是为什么局部变量的命名应与成员变量不同的原因之一。命名约定有助于避免此类错误。
作为一个附带说明,或者更确切地说是一个非常重要的说明,由于您的类管理资源,请考虑正确地实现复制语义和析构函数:此规则通常被称为三规则。或者使用一些智能指针,如std::shared_ptr
、std::unique_ptr
或任何适合您场景的指针。
Nawaz的回答是正确的。但除此之外,您的代码还有几个可能的问题:
- 如果有人创建了SkyMap,并且从未使用它调用DrawAitoffSkymap,那么您将获得未定义的行为(由于mSkymapBorderBox从未初始化,因此它将具有一个随机值,然后您将其删除)
- 如果有人用给定的SkyMap多次调用DrawAitoffSkymap,那么您将出现内存泄漏
要修复:
(1) 在构造函数中将mSkymapBorderBox初始化为零。
(2) 决定DrawAitoffSkymap在多次调用时应该做什么。如果它应该重用旧的mSkymapBorderBox,那么你会想说这样的话:
void Skymap::DrawAitoffSkymap() {
if (!mSkymapBorderBox) mSkymapBorderBox = new TBox(...);
...
}
另一方面,如果每次都要创建一个新的TBox,那么您需要:
void Skymap::DrawAitoffSkymap() {
delete mSkymapBorderBox; // note: does nothing if mSkymapBorderBox == 0
mSkymapBorderBox = new TBox(...);
...
}
TBox* mSkymapBorderBox=new TBox(-200,-100,200,100);
您正在创建一个新的TBox*
指针,它不是数据成员。
考虑在实现new
之后,在同一逻辑单元/范围内正确实现delete
。。。
TBox* mSkymapBorderBox=new TBox(-200,-100,200,100);
当您声明这一点时,这将创建一个TBox类的对象。退出时DrawAitoffSkymap此时丢失了这个分配内存的引用。
当析构函数被调用时,它会释放一些垃圾内存。
要避免这种情况,请使用此mSkymapBorderBox=new TBox(-200,-100,200,100);
而不是TBox* mSkymapBorderBox=new TBox(-200,-100,200,100);
- 为什么要增加导致崩溃的指针
- 指针相关的UE4崩溃.我的指针哪里错了?
- 访问提升:shared_ptr 主范围外崩溃,断言失败:px != 0.指针的正确用法是什么?
- 当键是虚拟继承中涉及的基类指针时,对 std::unordered_map 项的访问崩溃
- 由于指针算法错误,代码在 memcpy 中崩溃
- 使用唯一指针调用函数会使我的程序崩溃
- 智能指针的排序向量:神秘崩溃
- 类指针方法崩溃程序
- 在C++中删除指针数组时析构函数崩溃
- 使用push_back方法获取智能指针矢量时应用崩溃
- 为什么此代码在此 Trie 实现中使用映射 c++ 中的指针崩溃?
- 从 GetProcAddress 获取的函数指针在使用 stdlib 时会使程序崩溃
- 在函数内部错误定位后,从函数中释放返回的指针会导致芯片崩溃
- 为什么此自定义指针类会崩溃?
- 函数和指针帮助:程序生成,但崩溃,没有任何特定错误
- 定义指针随机崩溃该程序
- 在崩溃时释放分配的指针的正确方法
- C++ Cout 在使用指针时崩溃
- 取消引用会导致崩溃,即使对于非 NULL 指针也是如此,原因也是如此
- 为什么此代码可能会在C++中崩溃(指针返回)