删除在另一个对象的构造函数中创建的“新对象”?

时间:2013-02-08 13:15:38

标签: c++ object memory-leaks

在我的程序中,我有以下typedef:

typedef shared_ptr<IFrameObserver> IFrameObserverPtr;

以后,这行代码:

IFrameObserverPtr myObv(new MyObserver(cameras[0]))

。 。 。其中MyObserver是在IFrameObserverPtr的构造函数中创建的。问题是MyObserver类每次创建时都会创建一个6mB的位图,并且由于它永远不会被删除,这会导致非常严重的内存泄漏(此行每秒调用10次)。

我的问题很简单:如何明确删除新的MyObserver以避免这种内存泄漏?

关于我的内存泄漏是多么可怕的参考,在部分执行我的程序期间,这是我的任务管理器:

horrible memory leak


编辑:好的,我花了最后2个小时试图解决这个问题无济于事。做。 。 。

myObv.reset();

。 。 。没用。

这样每个人都可以看到MyObserver类中发生了什么,这里是:

class MyObserver : public IFrameObserver
{
public:

    HBITMAP hbm;

    BITMAPINFOHEADER* bi;

    MyObserver(CameraPtr pCamera) : IFrameObserver(pCamera) {};
    ~MyObserver(){delete hbm;}

    HBITMAP GetBMP()
    {
        return hbm;
    }

    void FrameReceived ( const FramePtr pFrame )  
    {
        DbgMsg(L"Frame Received\n");


        //////////////////////////////////////////////////////////////////////////
        //////////  Set Bitmap Settings   ////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////////

        //fileheader
        BITMAPFILEHEADER* bf = new BITMAPFILEHEADER;
        bf->bfType = 0x4d42;
        bf->bfSize = 6054400 + 54;
        bf->bfOffBits = 54;

        //infoheader
        bi = new BITMAPINFOHEADER;
        bi->biSize = 40;
        bi->biWidth = 2752;
        bi->biHeight = -733;
        bi->biPlanes = 1;
        bi->biBitCount = 24;
        bi->biCompression = 0;
        bi->biSizeImage = 6054400;
        bi->biXPelsPerMeter = 2835;
        bi->biYPelsPerMeter = 2835;
        bi->biClrUsed = 0;
        bi->biClrImportant = 0;

        //image data in VmbPixelFormatMono8
        VmbUchar_t* imageData;
        pFrame->GetImage(imageData);


        //////////////////////////////////////////////////////////////////////////
        //////////  Output File to .bmp   ////////////////////////////////////////
        //////////////////////////////////////////////////////////////////////////

        BITMAPINFO* bmi;
        bmi = (BITMAPINFO*)bi;

        HDC hdc = ::GetDC(NULL);

        hbm = CreateDIBitmap(hdc, bi, CBM_INIT, imageData, bmi, DIB_RGB_COLORS);

        delete  bf;
        delete  bi;
        //free(imageData); //doesn't work, crashes
        //delete imageData; //doesn't work, crashes
        imageData = NULL;   //doesn't crash, but I don't think this frees the memory
        DeleteObject(hdc);  



    }
};

我已经尝试了所有我想到的东西来释放这些物体在创建时所产生的5.77 mB,而我无法弄清楚如何去做。

3 个答案:

答案 0 :(得分:2)

假设您在评论中说typedef shared_ptr<IFrameObserver> IFrameObserverPtr,那么当它超出范围时,它会减少引用计数。

所以有几种可能性:

  1. 您使用的shared_ptr已损坏。如果它是boost ::或std :: shared_ptr。
  2. ,这是极不可能的
  3. 您正在将shared_ptr传递给另一个函数或对象,它会为同一个对象创建另一个shared_ptr,以防止其被破坏。在这种情况下,找到发生不需要的对象保留的位置。
  4. MyObserver销毁的析构函数不会释放位图。
  5. IFrameObserver的析构函数不是虚拟的,因此不会调用释放位图的MyObserver销毁。
  6. 所以第一个测试是确定是否:

    {
        IFrameObserverPtr myObv(new MyObserver(cameras[0]));
    }
    

    调用MyObserver析构函数。如果没有,则适用4或3。

    如果该块泄漏了位图,则~MyObserver出错。

    如果该块释放了位图,那么请查看保留该对象的其他内容。


    通过编辑显示析构函数和创建位图hbm的句柄的代码,显然析构函数不会破坏位图。

    由于您使用CreateDIBitmap创建了一个Win32 API调用hbm,您需要使用相应的Win32 API调用来释放它,msdn.microsoft.com / en-gb / library / windows / desktop / ...说是DeleteObject,而不是仅仅在位图的句柄上使用C ++删除 - 您正在尝试删除句柄(这是void*指针,因此是undefined behaviour)。你没有告诉Windows释放句柄指向的资源。

    你可能也在泄漏图像数据,因为已经注释了试图释放图像数据 - 检查文档Frame::GetImage(或任何调用是其实现的基础,如果它是你自己的代码)关于你是否需要调用任何可以解放的东西,或者它是否仍然属于框架。

答案 1 :(得分:0)

如果IFrameObserver实现是为了拥有你传递给它的构造函数的MyObserver,那么让它的析构函数删除它,然后确保IFrameObserver被及时销毁。如果其他人应该拥有MyObserver,请确保他们有一个指针并知道何时删除它。

如果你不知道谁应该拥有它,你需要弄明白。在C ++中实现内存管理的唯一方法是了解对象所有权和生命周期。完成整理后,shared_ptrunique_ptr等内容可让您轻松实现。

答案 2 :(得分:0)

  

IFrameObserverPtr的定义为typedef shared_ptr<T>(IFrameObserver) IFrameObserverPtr

     

问题是MyObserver类每次创建时都会创建一个6mB的位图

     

它永远不会被删除

我认为您的意思是typedef shared_ptr<IFrameObserver> IFrameObserverPtr,而您的计算机上有一个破损的复制/粘贴机制。

然后:

  1. MyObserver析构函数已损坏且必须修复,或
  2. MyObserver析构函数及其基础等效IFrameObserver析构函数未标记为virtual
  3. MyObserver对象本身在最后剩余的IFrameObserverPtr超出范围时已经被销毁,所以当修复该销毁过程以消除泄漏时,你会没事的。< / p>