ts4242 wrote:The message box was totally black, i was not able to see anything even the yes no buttons, i tried to switch to other app and back to TC to refresh the message box but it remains black.
GDI resources have been exhausted (7000 GDI objects), so painting of the message box failed.
ghisler(Author) wrote:Apparently CreateDIBSection failed, maybe one of the icons was bad.
In our case CreateDIBSection failed, because GDI handles have been exhausted. Theoretical maximum handles count per session (= per each user logged in) is 65535. But there is also a per-process limit, which is defined in a registry key (see
GDI Objects). In practice the limit is even lower than the registry key says, for my computer it is about 6200 GDI handles per process - see a test code below.
I put a lot of image files into a directory and tried to reproduce the problem. I noticed that initially Total Commander allocates GDI objects only for currently displayed thumbnails, but when I scroll down thumbnails in the panel, the number of allocated GDI objects increases. So there is a possibility of exhausting GDI handles when the panel contains a lot of thumbnails.
So two improvements can be done:
1) TCMD should free invisible buffered thumbnails (their DIB sections), if their number reaches, let's say, 2000. This will prevent exhausting the session limit for GDI handles and minimize the possibility, that other applications will fail due to lack of GDI resources.
2) TCMD should free invisible buffered thumbnails (their DIB sections) immediately, if CreateDIBSection failed. There is a possibility, that another application will use a lot of GDI handles and TCMD won't be able to allocate even 2000 GDI handles. Then TCMD should free all invisible buffered thumbnails and should try to display currently visible thumbnails again (try to call CreateDIBSection again).
However, I can't explain such a big memory usage. 32x32 icon with 24-bit color will use 32*32*3 = 3072 bytes of memory. Due to memory granularity (4096 bytes), CreateDIBSection will allocate 4096 bytes of memory for each icon. For 7000 icons, the memory usage will be 4096*7000 = 27.3 MB. So this is 10x less than in the bug report.
Testing maximum GDI handles count:
Code: Select all
program Test;
uses
Windows, SysUtils;
var
I : Integer;
Count : Integer;
BitmapInfo : TBitmapInfo;
BitmapBits : Pointer;
Bitmaps : array[0..1024*1024-1] of HBITMAP;
begin
with BitmapInfo, bmiHeader do
begin
biSize:=SizeOf(bmiHeader);
bmiHeader.biWidth:=32;
bmiHeader.biHeight:=32;
bmiHeader.biPlanes:=1;
bmiHeader.biBitCount:=24;
bmiHeader.biCompression:=BI_RGB;
bmiHeader.biSizeImage:=0;
bmiHeader.biXPelsPerMeter:=96;
bmiHeader.biYPelsPerMeter:=96;
bmiHeader.biClrUsed:=0;
bmiHeader.biClrImportant:=0;
end;
Count:=0;
for I:=0 to High(Bitmaps) do
begin
Bitmaps[I]:=CreateDIBSection(0,BitmapInfo,DIB_RGB_COLORS,BitmapBits,0,0);
if Bitmaps[I] = 0 then
begin
for Count:=0 to I-1 do
DeleteObject(Bitmaps[Count]);
Count:=I;
Break;
end;
end;
MessageBox(0,PChar('Bitmaps successfully created: '+IntToStr(Count)),'Result',0);
end.
Regards