如何检查Destructor中是否已释放内存?

时间:2009-11-02 15:02:10

标签: c++ memory-leaks destructor allegro

我使用allegro开源库进行简单的坦克大战风格游戏。在我的tank类中,我将位图对象的指针数组初始化为0.然后我使用allegro函数create_bitmap创建新对象,该函数分配内存并初始化它。

然后我像往常一样开展业务。

问题是,当我像类好的OO男孩那样在类析构函数中释放位图内存时,我崩溃了程序,因为在这个特定的程序中,allegro库进行清理(释放它创建的位图对象)在课程超出范围并被销毁之前。它不会再次将我的指针设置为NULL,所以我无法检查位图是否仍然有效,如果我尝试释放它们,它们将使程序崩溃。

这有什么办法吗?如果它们不是NULL,我可以检查有效指针吗?如果在程序中以不同的方式使用类,我怎么能确定释放内存。就目前而言,我基本上是在没有删除的情况下调用new而我不喜欢它。

9 个答案:

答案 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_bitmapdestroy_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)

在处理堆内存的多个指针时使用引用计数。基本上,如果您对同一个内存有多个引用并删除一个内存,则另一个引用可能仍然认为它存在。

http://en.wikipedia.org/wiki/Reference_counting

答案 8 :(得分:0)

我要说你应该确保在关闭Allegro之前你的对象都被破坏了,你可以通过(如果他们在堆栈上)关闭他们存在的范围而在关闭Allegro之前轻松地做到这一点。

如果您需要在此之前关闭Allegro(例如由于致命错误),那么您可以调用exit,在这种情况下不会运行析构函数(但您的程序仍然不会崩溃)。

不要花太多时间确保程序在退出时清理,节省您的努力以确保它在运行时不会泄漏:)