Delphi7程序出現“EOSError code8-存儲不足”問題的分析與解決


1,故障現象

 

 

 

 

 

程序長期運行后,出現"System Error. Code: 8. 存儲不足,無法處理此命令"錯誤。

 

此時檢查磁盤空間是足夠的。但打不開任務管理器。cmd命令行窗口都打不開。

關閉出錯程序后,也無法重啟。必須重啟操作系統才能恢復正常。

 

 

2,錯誤分析

https://stackoverflow.com/questions/507853/system-error-code-8-not-enough-storage-is-available-to-process-this-command

 

上文顯示,“Delphi apps are leaking atoms, leaving the id of your app without dropping it off from memory”,Delphi7使用了RWM Atom進行消息通信,但系統無法自動釋放,當16K的空間被分配完后,就會彈出該錯誤。

 

采用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

       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(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的消耗一直保持穩定。問題得到解決。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM