0

私のプログラムには、次の typedef があります。

typedef shared_ptr<IFrameObserver> IFrameObserverPtr;

そして、後で、このコード行:

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

. . . MyObserver は IFrameObserverPtr のコンストラクターで作成されます。問題は、MyObserver クラスが作成されるたびに 6mB のビットマップを作成し、削除されないため、かなり深刻なメモリ リークが発生することです (この行は 1 秒間に 10 回呼び出されます)。

私の質問は短くて簡単です。新しい MyObserver を明示的に削除して、このメモリ リークから身を守るにはどうすればよいですか?

私のメモリ リークがどれほどひどいものであるかについての参考として、プログラムの部分実行中のタスク マネージャを次に示します。

恐ろしいメモリリーク


編集:さて、私はこれを無駄に修正しようとして過去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 を解放するために考えられるすべてのことを試しましたが、その方法がわかりません。

4

3 に答える 3

2

typedef shared_ptr<IFrameObserver> IFrameObserverPtrあなたがコメントで言っていると仮定すると、範囲外になると参照カウントが減ります。

したがって、いくつかの可能性があります。

  1. 使用している shared_ptr が壊れています。これは、boost:: または std:: shared_ptr の場合はほとんどありません。
  2. shared_ptr を別の関数またはオブジェクトに渡すと、同じオブジェクトに別の shared_ptr が作成され、その破壊が防止されます。この場合、不要なオブジェクトの滞留が発生している場所を見つけます。
  3. MyObserver 破壊のデストラクタは、ビットマップを解放しません。
  4. IFrameObserver のデストラクタは仮想ではないため、ビットマップを解放する MyObserver 破壊を呼び出していません。

したがって、最初のテストは、次のことを判断することです。

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

MyObserver デストラクタを呼び出します。そうでない場合は、4 または 3 が適用されます。

そのブロックがビットマップをリークする場合、~MyObserver に障害があります。

そのブロックがビットマップを解放する場合は、オブジェクトを保持している他のものを調べます。


デストラクタとハンドルであるビットマップを作成するコードを表示する編集により、デストラクタがビットマップをhbm破棄しないことは明らかです。

Win32 API 呼び出しでhbm を作成するため、C++ の delete を使用するだけでなくCreateDIBitmap、対応する Win32 API 呼び出しで hbm を解放する必要があります。DeleteObjectビットマップへのハンドル - ハンドルを削除しようとしています (これはvoid*ポインターであるため、未定義の動作です)。ハンドルが指すリソースを解放するようにWindowsに指示していません。

コメントアウトされた解放の試みがあるため、画像データもリークしている可能性があります-それを解放するためFrame::GetImageに何かを呼び出す必要があるかどうか、またはそれがフレームが所有し続けます。

于 2013-02-08T13:53:37.137 に答える
0

IFrameObserver実装がMyObserverコンストラクタに渡すものを所有することを意図している場合は、デストラクタにそれを削除してもらい、すぐに破棄されることを確認してくださいIFrameObserver。他の誰かが所有していることになっMyObserverている場合は、彼らがポインタを持っていることを確認し、それをいつ削除するかを知ってください。

誰がそれを所有することになっているのかわからない場合は、それを理解する必要があります。C ++でメモリ管理を正しく行う唯一の方法は、オブジェクトの所有権とライフサイクルを理解することです。それを整理したら、次のようなものを使用すると、非常に簡単に実装できるようになりますshared_ptrunique_ptr

于 2013-02-08T13:38:51.430 に答える
0

anIFrameObserverPtrには定義がありますtypedef shared_ptr<T>(IFrameObserver) IFrameObserverPtr

問題は、MyObserverクラスが作成されるたびに 6mB のビットマップを作成することです。

削除されることはありません

typedef shared_ptr<IFrameObserver> IFrameObserverPtr使いのコンピューターのコピー/貼り付けメカニズムが壊れていると思います。

次に、次のいずれかを行います。

  1. デストラクタが壊れており、MyObserver修正する必要がある、または
  2. MyObserverデストラクタとその基本同等のデストラクタIFrameObserverはマークされていませんでしたvirtual

MyObserverオブジェクト自体は、最後に残っているオブジェクトが範囲外になると既に破棄されているIFrameObserverPtrため、その破棄プロセスが修正されてリークが除去されれば問題ありません。

于 2013-02-08T13:55:15.317 に答える