我使用allegro开源库进行简单的坦克大战风格游戏。在我的tank类中,我将位图对象的指针数组初始化为0.然后我使用allegro函数create_bitmap创建新对象,该函数分配内存并初始化它。
然后我像往常一样开展业务。
问题是,当我像类好的OO男孩那样在类析构函数中释放位图内存时,我崩溃了程序,因为在这个特定的程序中,allegro库进行清理(释放它创建的位图对象)在课程超出范围并被销毁之前。它不会再次将我的指针设置为NULL,所以我无法检查位图是否仍然有效,如果我尝试释放它们,它们将使程序崩溃。
这有什么办法吗?如果它们不是NULL,我可以检查有效指针吗?如果在程序中以不同的方式使用类,我怎么能确定释放内存。就目前而言,我基本上是在没有删除的情况下调用new而我不喜欢它。
答案 0 :(得分:5)
我认为问题不在于allegro会释放位图本身(或者你不需要在退出时释放它们)但是在调用析构函数之前,allegro库已被取消初始化。
int main()
{
ObjectManagingBitmaps o;
...
return 0;
//allegro automatically shut down here
} //o destructor invoked here
END_OF_MAIN()
您可以采取哪些措施来确保首先调用析构函数是使用人工作用域:
int main()
{
{
ObjectManagingBitmaps o;
...
} //o destructor invoked here
return 0;
//allegro automatically shut down here
}
END_OF_MAIN()
答案 1 :(得分:4)
您不应该使用原始指针数组。 Allegro附带create_bitmap
和destroy_bitmap
功能。这很好地映射了构造函数和析构函数的C ++概念。你应该有一个AllegroPlusPlus::bitmap
类,它只管理一个位图。你的Tank类可以简单地使用tehn。
这是责任的分离。 tank类不应该对位图及其memoy管理有太多的了解,而bitmap类应该只处理一个位图。
您想在Tank类中回收位图。这没问题;通过良好实现bitmap::operator=(bitmap const&)
或其他重载,可以轻松完成。但同样,让该分配成为位图类的责任,而不是坦克类。
答案 2 :(得分:2)
如果它们不是NULL,我可以检查有效指针吗?
没有。但在你的情况下,你不需要。由于Allegro承诺会处理其资源,因此您不必(也不得)干预Allegro资源的资源处理。特别是,由于您甚至不知道如何分配资源,因此您无法取消分配资源。
答案 3 :(得分:1)
明确管理内存的关键是,虽然你可以有几个指向同一个内存区域的指针,但在任何时候,只有其中一个是指定的所有者,而所有其他只是共享它。当堆对象拥有其他堆对象时,它们构成一个树,以某个地方的全局或本地范围的变量为根。
一旦从最初的Allegro调用返回,您应该认为Allegro是您传入其中的内存区域的所有者,并且您自己的指针只是一个共享指针。
不,除非有一些分配器技巧,否则你没有标准方法来确定内存是否有效。分配器技巧可用于调试目的,但不要弄乱库的内部。
答案 4 :(得分:1)
听起来很恐怖leaky abstraction
如果您不确切知道如何分配内存,则无法找到一种破坏内存的安全方法。清理功能听起来就像是有原因并且做一份工作 - 只需要接受它。
你当然可以包装这些位并在注释中包含一些文档,以便其他开发人员不会陷入相同的陷阱。
还要对您的申请进行分析,以确保没有泄漏。
答案 5 :(得分:1)
什么时候被调用析构函数?是在Allegro库被关闭之后吗?如果是,那么你可以先删除所有对象吗?
答案 6 :(得分:0)
你确定你正确使用它吗?我挖出了一些旧的Allegro代码,我有一个带有create_bitmap调用的构造函数和一个带有release_bitmap调用的析构函数,它工作正常。
我不记得有关Allegro自动为您释放内存的任何事情。你是否意外用一些非内存值覆盖指针?还有另一个地方释放了这个指针吗?
答案 7 :(得分:0)
在处理堆内存的多个指针时使用引用计数。基本上,如果您对同一个内存有多个引用并删除一个内存,则另一个引用可能仍然认为它存在。
答案 8 :(得分:0)
我要说你应该确保在关闭Allegro之前你的对象都被破坏了,你可以通过(如果他们在堆栈上)关闭他们存在的范围而在关闭Allegro之前轻松地做到这一点。
如果您需要在此之前关闭Allegro(例如由于致命错误),那么您可以调用exit,在这种情况下不会运行析构函数(但您的程序仍然不会崩溃)。
不要花太多时间确保程序在退出时清理,节省您的努力以确保它在运行时不会泄漏:)