删除在堆上存储数据的堆中的对象
我的程序是使用SDL库中的类编写的。
我有以下课程:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** F;
float* F_current;
unsigned int S_total;
unsigned int S_current;
public:
s_group(void);
virtual ~s_group(void);
bool setup( const char* filename, unsigned int s );
//other member functions
};
私有成员指针每个存储在堆上声明的内存位置,由成员函数setup
分配。
bool s_group::setup( const char* filename, unsigned int s )
{
s_group::~s_group();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
F = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
F[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
在一个大函数中,我在堆上创建了这个类的一个对象,将其地址存储在一个名为sparkle
的s_group
指针中。
s_group* sparkle = new s_group;
sparkle->setup("sparkle_final.png", 1 );
完成该函数后,我调用delete
来重新分配堆内存。 删除这条线解决了这个问题,然而这会导致内存泄漏。
delete sparkle;
sparkle = NULL;
这将调用该类的析构函数,这是我认为由于内部使用delete
操作符而发生错误的地方。
s_group::~s_group(void)
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
F[s][f].x = 0;
F[s][f].y = 0;
F[s][f].w = 0;
F[s][f].h = 0;
}
delete[] F[s];
F[s] = NULL;
}
delete[] F;
F = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
到达删除操作员时,会出现一个对话框,指出:
Windows已经在Program.exe中触发了一个断点。 这可能是由于堆的损坏,这表明Program.exe或它已加载的任何DLL中存在一个错误。
如何在不导致堆损坏的情况下delete
此对象?
来自有效的C ++ Scott Meyers
第9项:在施工或销毁期间切勿调用虚拟功能。
在施工或销毁期间,你不应该调用虚函数,因为这些调用不会做你的想法,如果他们这样做,你仍然会不高兴。 如果您是恢复Java或C#程序员,请密切关注此项目,因为这是一种使用C ++ zags的语言缩写的地方。
实际上,即使你应该定义你的析构函数,强行调用它应该是不可能的
我无法编译你的代码,但在这里..
我注意到的第一件事就是你叫你的析构函数。你不想这么做! 相反,创建一个释放函数并调用它。
我注意到的下一件事是类本身没有FRAME
变量..所以这一行:
FRAME = new SDL_Rect*[S_total];
会导致编译错误,并且你的析构函数使用FRAME
但不存在这样的变量。 我想你的意思是把它改为F
因为如果不是的话,那么这一行:
F[index] = NULL;
是未定义的行为,因为F是未初始化的..
此外,您从未初始化FRAME
每个索引,因此在析构函数中访问它,如:
FRAME[s][f].x = 0;
是一个禁忌。
再次,你打电话
delete[] F;
F = NULL;
但F没有分配内存并且未初始化。
因此,我认为所有的补丁:
class s_group
{
private:
SDL_Surface* image;
unsigned int* F_total;
float* F_length;
SDL_Rect** FRAME;
float* F_current;
unsigned int S_total;
unsigned int S_current;
void Release();
public:
s_group(void);
virtual ~s_group(void);
bool setup(const char* filename, unsigned int s);
//other member functions
};
bool s_group::setup(const char* filename, unsigned int s)
{
Release();//delete already allocated heap memory
if(!load_file(image, filename))
{
image = NULL;
return false;
}
S_total = s;
FRAME = new SDL_Rect*[S_total];
F_total = new unsigned int[S_total];
F_length = new float[S_total];
F_current = new float[S_total];
for(unsigned int index = 0; index < S_total; ++index)
{
FRAME[index] = NULL;
F_total[index] = 0;
F_length[index] = 0.f;
F_current[index] = 0.f;
}
//loop for each array slot and set values of data
return true;
}
void s_group::Release()
{
SDL_FreeSurface(image);
image = NULL;
for(unsigned int s = 0; s < S_total; ++s)
{
for(unsigned int f = 0; f < F_total[s]; ++f)
{
if (FRAME[s])
{
FRAME[s][f].x = 0;
FRAME[s][f].y = 0;
FRAME[s][f].w = 0;
FRAME[s][f].h = 0;
}
}
delete[] FRAME[s];
FRAME[s] = NULL;
}
delete[] FRAME;
FRAME = NULL;
delete[] F_total;
F_total = NULL;
delete[] F_length;
F_length = NULL;
delete[] F_current;
F_current = NULL;
S_total = 0;
S_current = 0;
}
s_group::~s_group(void)
{
Release();
}
应该这样做..只是不要忘记为FRAME[index]
分配内存我不知道多少或你想分配什么,所以我改变了Release
功能,以检查FRAME[index]
是否有效与if-statement
我强烈建议您使用一些SmartPointers
并忘记自己处理每一个内存分配。
自发布这个问题以来,我找到了错误的来源并解决了问题。 在为动态2D数组设置数据值的单独代码段中,循环验证不正确。
for( unsigned int index = 0; index <= F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
可以看出,循环显然会尝试修改等于创建数组大小的位置。 当然,注意到数组从索引0开始,因此最终的插槽将大小为-1。写代码时我错过了一些非常愚蠢的事情。 实际循环:
for( unsigned int index = 0; index < F_total[ S_current ]; ++index ) {
//set data values for each slot in the array
F[ S_current ][ index ].x = 0; etc...
}
给任何尝试自己的内存管理的人的消息:
上一篇: Deleting objects on the heap which store data on the heap