2011-10-30 73 views
3

當我嘗試設置BMP.Height或BMP.Width時,嘗試使用BMP文件時,出現「EOutofresources - 存儲空間不足」。在這些指令後,立即執行堆棧跟蹤(按此順序): ntdll.dll.RtlLeaveCriticalSection,kernel32.dll.FileTimeToDosDateTime,GDI32.dll.GdiReleaseDC,GDI32.dll.PatBlt,kernel32.dll.ReadFile或如下所示:使用位圖時出現「存儲空間不足」錯誤

|7E429130|user32.dll   GetParent     
|7C90FF2D|ntdll.dll   RtlGetNtGlobalFlags  
|77F15A00|GDI32.dll   GdiReleaseDC 
|7C83069E|kernel32.dll  FileTimeToDosDateTime 
|7C9010E0|ntdll.dll   RtlLeaveCriticalSection 
|  |my function (where I set BMP.Height or BMP.Width) 

此刻我確信它必須做一些內存碎片 - 系統有足夠的空閒RAM來處理我的映像,但內存碎片化,所以沒有足夠大的塊來保存我的映像。但之後我在Windows啓動11秒後就看到它發生了。我的程序在循環中循環,只處理一次圖像!所以,這不能與RAM碎片相關。

不同的情況(但仍與繪圖),當我得到這個錯誤是下面:

|77F16A7E|GDI32.dll   IntersectClipRect  
|77F16FE5|GDI32.dll   BitBlt    
|7E429011|user32.dll   OffsetRect   
|7E42A97D|user32.dll   CallWindowProcA   
|7E42A993|user32.dll   CallWindowProcA   
|7C9010E0|ntdll.dll   RtlLeaveCriticalSection 
|7E4196C2|user32.dll   DispatchMessageA  
|7E4196B8|user32.dll   DispatchMessageA  
|0058A2E1|UTest.exe   UTest.dpr 
|7C90DCB8|ntdll.dll   ZwSetInformationThread 

我想總會有BMP.Height後的堆棧跟蹤「RtlLeaveCriticalSection」呼叫。

this後指向一個可能的解決方案通過編輯Windows註冊表項。但是,這篇文章說它只適用於Win XP。雖然也出現在Win 7


我的錯誤,我看到很多類似的帖子(其中有些是接近連接到文件保存到磁盤),但直到沒人回來報告說,他固定的錯誤。


更新:

根據你的要求,這就是出現錯誤代碼:

procedure TMyBitmap.SetLargeSize(iWidth, iHeight: Integer); 
CONST ctBytesPerPixel= 3; 
begin 
{ Protect agains huge/empty images } 
if iWidth<  1 then iWidth:=  1 else 
if iWidth> 32768 then iWidth:= 32768; 

if iHeight<  1 then iHeight:=  1 else 
if iHeight> 32768 then iHeight:= 32768; 

{ Set image type } 
if iWidth * iHeight * ctBytesPerPixel > 9000000 {~9MB}      
then HandleType:= bmDIB           { Pros and cons: -no hardware acceleration, +supports larger images } 
else HandleType:= bmDDB;              

{ Total size is higher than 1GB? } 
if (iWidth* iHeight* ctBytesPerPixel) > 1*GB then 
    begin 
    Width := 8000;               { Set a smaller size } 
    Height := 8000;               { And rise an error } 
    RAISE Exception.Create('Image is too large.'); 
    end; 

{ Set size } 
Width := iWidth;       <----------------- HERE 
Height:= iHeight; 
end; 
+1

請顯示源代碼...它聽起來更像是一個資源泄漏(即處理泄漏)比內存問題... – Yahia

+0

位圖有多大? –

+0

位圖可以有任何大小。通常他們應該是正常的數碼相機圖片(4-16 Mpixels)。 – Ampere

回答

4

從我的實驗,最大位圖大小取決於:

  • 操作系統版本(例如XP似乎允許比七更小的位圖資源);
  • OS版(64位操作系統允許比32位操作系統更大的資源分配);
  • 當前安裝的RAM(和免費);
  • 已分配的位圖數(因爲這些是共享資源)。

因此,當您開始處理大量數據(不僅僅是屏幕上的位圖分辨率)時,您無法確定位圖分配是否成功。

這裏有一些可能的解決方案(我已經使用了其中的一些):

  • 分配不是一個位圖資源,而是一個普通的內存塊的工作,然後用直接的Win32 API的BitBlt畫它 - 但您必須編寫一些專用的進程函數(或使用某些第三方庫),並且在32位操作系統上,恕我直言,VirtualAlloc API(FastMM4稱爲大內存塊)將無法分配超過1 GB的連續內存;
  • 以前版本的增強:使用64位進程處理巨大的RAM塊(歡迎使用XE2編譯器),或者使用文件進行臨時存儲,然後對其內容進行內存映射處理(PhotoShop或其他處理巨大的內存) - 如果你有足夠的內存,使用臨時文件將不必要慢(數據不會寫在磁盤上);
  • 將大圖片拼貼成更小的圖片 - JPEG庫只能渲染圖片的一部分,並且可以很容易地放入位圖資源;
  • 在所有情況下,防止任何重複的位圖資源(因爲所有的位圖資源都是共享的):例如,如果您正在從位圖中讀取,請將其內容複製到臨時內存塊或文件中,釋放其資源,然後分配目的地位圖;
  • 關於性能,做對,然後加快速度 - 在實施過程中不要過早包含「技巧」(您的客戶可能會接受等待幾秒鐘,但不會接受全局故障)。

沒有完美的解決方案(我的偏好是使用更小的圖片,因爲它具有輕鬆處理多線程的優勢,所以可能會加速很多新的CPU),並且要知道資源分配可能適用於您的全新64位Windows 7 PC,但在客戶的32位XP計算機上失敗。

相關問題