我的程序是使用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;
}
在一个大函数中,我在堆上创建了这个类的对象,将其地址存储在名为s_group
的{{1}}指针中。
sparkle
完成该函数后,我调用s_group* sparkle = new s_group;
sparkle->setup("sparkle_final.png", 1 );
来重新分配堆内存。删除此行可以解决问题,但是会出现内存泄漏。
delete
这将调用类的析构函数,我认为由于delete sparkle;
sparkle = NULL;
运算符的内部使用而导致错误发生。
delete
在到达删除操作符时,会出现一个对话框,说明:
Windows在Program.exe中触发了断点。这可能是由于堆的损坏,这表明Program.exe或它已加载的任何DLL中存在错误。
如何在不导致堆损坏的情况下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;
}
此对象?
答案 0 :(得分:2)
你不应该在构造或破坏期间调用虚函数,因为调用不会按照你的想法进行,如果有的话,你仍然会不高兴。如果你是一个正在恢复的Java或C#程序员,请密切关注这个项目,因为这是这些语言的地方,而C ++ zags。
答案 1 :(得分:0)
我无法编译你的代码但是这里......
我注意到的第一件事是你打电话给你的析构函数..你不想这样做!相反,创建一个释放函数并调用它。
我注意到的下一件事是类本身内没有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
并忘记自己处理每一个内存分配..
答案 2 :(得分:0)
自发布此问题以来,我找到了错误的来源并解决了问题。 在为动态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...
}
任何人尝试自己的内存管理的消息: