Delphi7程式出現“EOSError code8-儲存不足”問題的分析與解決
阿新 • • 發佈:2021-01-20
1,故障現象
程式長期執行後,出現"System Error. Code: 8. 儲存不足,無法處理此命令"錯誤。
此時檢查磁碟空間是足夠的。但打不開工作管理員。cmd命令列視窗都打不開。
關閉出錯程式後,也無法重啟。必須重啟作業系統才能恢復正常。
2,錯誤分析
上文顯示,“Delphi apps are leaking atoms, leaving the id of your app without dropping it off from memory”,Delphi7
採用ATOMTableMonitor程式觀察發現,RWM ATom的消耗每天約增加2000,因此很快16K的空間將耗盡,最終將導致錯誤。
3,解決方案
http://cc.embarcadero.com/Item/28963
以上網站提供了釋放RWM Atom資源的補丁。其中修復原理為Atom重複使用,避免不斷分配新的Atom,具體說明如下:
There is a file called "RWMFixUnit.pas" that contains the hack, it replaces the call to RWM in the Controls unit and uses the GlobalAtom value (that will get cleaned up)
instead of the leaky RWM. You HAVE to add this unit before the Controls (otherwise it will complain!) and it will only work in statically linked applications.
I have simplified the implementation, so it will just reuse the global atom for the "ControlOfs" leak, all other RWM allocation will proceed as normal.
實際操作中,發現在Dephi7中編譯"RWMFixUnit.pas" 檔案時,出現錯誤
function IntrRegisterWindowMessage(lpString: PWideChar): UINT; stdcall; begin Result := 0; try if Pos('ControlOfs',lpString) = 1 then Result := GlobalFindAtom(lpString); //This is for defensive reasons... not really needed ifResult = 0 then begin //if we get here we know that the GlobalAtom has not been allocated yet //so this is ***not*** the leaky ControlOfs RWM as Atom if @OrgRWMPtr <> nil then Result := OrgRWMPtr(lpString);
原因是GlobalFindAtom不接受PWideChar型別的引數。
因此,注意要修改為以下:
function IntrRegisterWindowMessage(lpString: PChar): UINT; stdcall; begin Result := 0; try if Pos('ControlOfs',lpString) = 1 then Result := GlobalFindAtom((lpString)); //This is for defensive reasons... not really needed if Result = 0 then begin //if we get here we know that the GlobalAtom has not been allocated yet //so this is ***not*** the leaky ControlOfs RWM as Atom if @OrgRWMPtr <> nil then Result := OrgRWMPtr(PWideChar(lpString));
修改後的程式,經過多日觀察,RWM Atom的消耗一直保持穩定。問題得到解決。