简体   繁体   中英

delete a “new object” created in the constructor of another object?

In my program I have the following typedef:

typedef shared_ptr<IFrameObserver> IFrameObserverPtr;

And, later, this line of code:

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

. . . in which MyObserver is created in the constructor of IFrameObserverPtr. The problem is that the MyObserver class creates a 6mB bitmap each time it gets created, and since it's never getting deleted, this causes a pretty severe memory leak (this line gets called 10 times a second).

My question is short and simple: How do I explicitly delete the new MyObserver to save myself from this memory leak?

For a reference as to how utterly horrible my memory leak is, here is my task manager during a partial execution of my program:

可怕的内存泄漏


EDIT: Okay I've spent the last 2 hours trying to fix this to no avail. Doing . . .

myObv.reset();

. . . didn't work.

Just so everyone can see what's going on inside the MyObserver class, here it is:

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);  



    }
};

I've tried everything I can think of to free the 5.77 mB this objects makes when it's created, and I cannot figure out how to do it.

Assuming typedef shared_ptr<IFrameObserver> IFrameObserverPtr as you say in your comment, then it will decrement the reference count when it goes out of scope.

So there are several possibilities:

  1. The shared_ptr you are using is broken. This is highly unlikely if it's a boost:: or std:: shared_ptr.
  2. You are passing the shared_ptr into another function or object and it creates another shared_ptr to the same object, preventing its destruction. In this case, find where the unwanted object retention is taking place.
  3. The destructor for MyObserver destruction does not free the bitmap.
  4. The destructor for IFrameObserver is not virtual and so is not calling the MyObserver destruction which frees the bitmap.

So the first test is to determine whether this:

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

calls the MyObserver destructor. If not, then 4 or 3 will apply.

If that block leaks the bitmap, then ~MyObserver is faulty.

If that block frees the bitmap, then look into what else is retaining the object.


With your edit showing the destructor and the code which creates the bitmap for which hbm is the handle, it's obvious that the destructor does not destroy the bitmap.

Since you create hbm with CreateDIBitmap , a Win32 API call, you need to release it with the corresponding Win32 API call, which msdn.microsoft.com/en-gb/library/windows/desktop/… says is DeleteObject , rather than just using C++ delete on the handle to the bitmap - you're trying deleting the handle (which is a void* pointer so is undefined behaviour ). You're not telling Windows to free the resource the handle points to.

You possibly are also leaking the image data, since there are commented out attempts to free it - check the documentation Frame::GetImage (or whatever call underlies its implementation if it's your own code) as to whether you have to call anything to free that, or whether it remains owned by the frame.

If the IFrameObserver implementation is meant to own the MyObserver you're passing to its constructor, get its destructor to delete it and then make sure IFrameObserver gets destroyed promptly. If someone else is supposed to own the MyObserver make sure they have a pointer and know when to delete it.

If you don't know who's supposed to own it, you need to figure it out. The only way to get your memory management right in C++ is to understand object ownership and lifecycles. Once you get that sorted out, things like shared_ptr and unique_ptr should allow you to implement it quite easily.

an IFrameObserverPtr has the definition typedef shared_ptr<T>(IFrameObserver) IFrameObserverPtr

The problem is that the MyObserver class creates a 6mB bitmap each time it gets created

it's never getting deleted

I assume you meant typedef shared_ptr<IFrameObserver> IFrameObserverPtr and your computer has a broken copy/paste mechanic.

Then either:

  1. the MyObserver destructor is broken and must be fixed, or
  2. the MyObserver destructor and its base equivalent the IFrameObserver destructor were not marked virtual .

The MyObserver object itself will already be destroyed when the last remaining IFrameObserverPtr to it goes out of scope, so when that destruction process is fixed to remove the leak, you'll be fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM