简体   繁体   English

分配TImage组件的位图句柄中的内存泄漏

[英]Memory Leak in Assigning Bitmap Handle of TImage component

Assuming I have a TImage component placed on a form along with a TButton. 假设我将一个TImage组件与一个TButton一起放置在窗体上。 When I click the button I run the code that follows. 当我单击按钮时,我运行下面的代码。 Ignoring the palette (I know how to create a grayscale palette and assign it) the following code works: 忽略调色板(我知道如何创建灰度调色板并为其分配),以下代码有效:

BYTE bBits[] = { 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88,
         0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00,
         0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22,
         0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44 };

Image1->Picture->Bitmap->Width=32;
Image1->Picture->Bitmap->Height=32;
Image1->Picture->Bitmap->PixelFormat = pf8bit;
SetBitmapBits(Image1->Picture->Bitmap->Handle,32*32,&bBits);

Now if I try this: 现在,如果我尝试这样做:

BYTE bBits[] = { 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88,
         0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00,
         0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22,
         0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44 };


HBITMAP HBmp = CreateBitmap(32, 32, 1, 8, bBits);
Image1->Picture->Bitmap->Handle=HBmp;

It does not work - it displays nothing. 它不起作用-它什么也不显示。 But if I change the CreateBitmap code to: 但是,如果我将CreateBitmap代码更改为:

HBITMAP HBmp = CreateBitmap(32, 32, 1, 8, bBits);

it displays however a monochrome image which is incorrect anyway. 但是它显示的单色图像仍然是错误的。

The real "weirdness" though is this: 真正的“怪异”是这样的:

BYTE bBits[] = { 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88,
         0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00,
         0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22,
         0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44 };
Image1->Picture->Bitmap->Width=32;
Image1->Picture->Bitmap->Height=32;
Image1->Picture->Bitmap->PixelFormat = pf8bit;
HBITMAP HBmp = CreateBitmap(32, 32, 1, 8, bBits);
Image1->Picture->Bitmap->Handle=HBmp;

Again nothing displays but if I click the button twice, I get an out of resources exception so it appears there is a memory leak. 再次没有显示任何内容,但是如果我单击按钮两次,则会出现资源不足异常,因此它似乎存在内存泄漏。

Finally if I change the order: 最后,如果我更改顺序:

HBITMAP HBmp = CreateBitmap(32, 32, 1, 8, bBits);
Image1->Picture->Bitmap->Handle=HBmp;
Image1->Picture->Bitmap->Width=32;
Image1->Picture->Bitmap->Height=32;
Image1->Picture->Bitmap->PixelFormat = pf8bit;

results in an instant exception (ie only need click the button once). 导致立即发生异常(即只需单击一次按钮)。

Note this memory leak has nothing to do with the original bitmap handle of the TImage ie Image1->Picture->Bitmap->Handle is NULL to begin with so there is no exisitng HBITMAP to release and DeleteObject etc. I am assuming when HBITMAP is assigned to TImage1's handle that TImage takes ownership. 请注意,此内存泄漏与TImage的原始位图句柄无关,即Image1-> Picture-> Bitmap-> Handle首先为NULL,因此没有释放的HBITMAP和DeleteObject等。我假设当HBITMAP为分配给TImage1的句柄,即TImage拥有所有权。

Any explanation? 有什么解释吗? Thank you in advance. 先感谢您。

PS: For reference sake this is how I did it with SetBitmapBits which worked: PS:作为参考,这是我使用SetBitmapBits起作用的方式:

BYTE bBits[] = { 128, 128, 128, 128, 0x00, 0x22, 0x44, 0x88,
         0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00,
         0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22,
         0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44 };

TMaxLogPalette lp;
lp.palVersion = 0x0300;
lp.palNumEntries = 256;

for (int i = 0; i < 256; i++) {
    lp.palPalEntry[i].peRed   = i;
    lp.palPalEntry[i].peGreen = i;
    lp.palPalEntry[i].peBlue  = i;
    lp.palPalEntry[i].peFlags = PC_RESERVED;
}

HPALETTE pal= CreatePalette((LOGPALETTE*)&lp);

Image1->Picture->Bitmap->Width=32;
Image1->Picture->Bitmap->Height=32;
Image1->Picture->Bitmap->PixelFormat = pf8bit;
Image1->Picture->Bitmap->Palette = pal;
SetBitmapBits(Image1->Picture->Bitmap->Handle,32*32,&bBits);

Ok figured part of it out: 确定找出其中的一部分:

As soon as you do this: 一旦您这样做:

Image1->Picture->Bitmap->Width=32;
Image1->Picture->Bitmap->Height=32;
Image1->Picture->Bitmap->PixelFormat = pf8bit;

Image1 creates a new HBITMAP so the reference to the bitmap: Image1创建一个新的HBITMAP,因此对位图的引用:

HBITMAP HBmp = CreateBitmap(32, 32, 1, 8, bBits);

gets lost without memory cleanup - hence a memory leak. 会在没有清除内存的情况下丢失,从而导致内存泄漏。

However I still don't get why: 但是我仍然不明白为什么:

HBITMAP HBmp = CreateBitmap(32, 32, 1, 8, bBits);
Image1->Picture->Bitmap->Handle=HBmp;

doesn't work. 不起作用。

To clarify the following code works without leaking: 为了澄清以下代码而不会泄漏:

BYTE bBits[] = { 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88,
     0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00,
     0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22,
     0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44 };


HBITMAP h= Image1->Picture->Bitmap->Handle;

if (h) {
Image1->Picture->Bitmap->ReleaseHandle();
DeleteObject(h);
}
Image1->Picture->Bitmap->Width=32;
Image1->Picture->Bitmap->Height=32;
Image1->Picture->Bitmap->PixelFormat = pf8bit;
h= Image1->Picture->Bitmap->Handle;
Image1->Picture->Bitmap->ReleaseHandle();
DeleteObject(h);

HBITMAP HBmp = CreateBitmap(32, 32, 1, 8, bBits);
Image1->Picture->Bitmap->Handle=HBmp;

Note that 注意

Image1->Picture->Bitmap->ReleaseHandle();
DeleteObject(h);

is necessary before and after. 之前和之后都是必要的。 The first time the button is clicked the before is unnecessary since h will be null, however on subsequent clicks it is. 第一次单击该按钮之前是不需要的,因为h将为null,但是在随后的单击中是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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