2014-06-23 25 views
0

以下代碼在我的計算機上似乎可以正常工作,但會爲客戶提供訪問衝突。行之間的訪問衝突

procedure TSummaryThread.Execute; 
var 
    When: String; 
begin 
    try 
    FCarcassListCS := TCriticalSection.Create; 
    FCarcassLists := TObjectList.Create; 
    while (not Terminated) do 
     begin 
     try 
      When := 'GetMessage'; 
      if (GetMessage(Msg, 0, 0, 0)) 
      then begin 
        if (Msg.message = WM_SUMMARISE) 
        then begin 
         When := 'WM_SUMMARISE'; 
         Update(True); 
         end 
       else if (Msg.message = WM_UPDATE) 
        then begin 
         When := 'WM_UPDATE'; 
         Update(False); 
         end 
       else if (Msg.message = WM_RELOAD_SETUP) 
        then begin 
         When := 'WM_RELOAD_SETUP'; 
         ReloadSetup(Pointer(Msg.wParam)); 
         end 
       else if (Msg.message = WM_SEND_TO) 
        then begin 
         When := 'WM_SEND_TO'; 
         SendToThread(Pointer(Msg.wParam)); 
         end 
       else if (Msg.message = WM_UPDATE_ORDER_SUM) 
        then begin 
         When := 'WM_UPDATE_ORDER_SUM'; 
         DoOrderSummary; 
         end 
       else if (Msg.message = WM_SUMMARISE_LOAD) 
        then begin 
         When := 'WM_SUMMARISE_LOAD'; 
         LoadAndSummarise; 
         end 
        else begin 
         When := 'DispatchMessage'; 
         DispatchMessage(Msg); 
         end; 
       end; 
     except 
      on E: Exception do 
      Log('Exception (' + E.ClassName + ') in summary thread at ' + When + ': ' + E.Message); 
     end; 
     end; 
    except 
    on E: Exception do 
     Log('Exception (' + E.ClassName + ') in summary thread (2) at ' + When + ': ' + E.Message); 
end; 

procedure TSummaryThread.Update(Full: Boolean); 
var 
    CarcassList: TObjectList; 
    Where: String; 
begin 
    try 
    Where := 'GetList'; 
    FCarcassListCS.Enter; 
    try 
     if (FCarcassLists.Count = 0) 
     then raise Exception.Create('No carcass list found'); 
     CarcassList := FCarcassLists[0] as TObjectList; 
     FCarcassLists.Extract(CarcassList); 
    finally 
     FCarcassListCS.Leave; 
    end; 
    FSummaryListCS.Enter; 
    try 
     Where := 'LoadFiles'; 
     SetFiles; 
     try 
     Where := 'AddCcs'; 
     CarcassList := GetShiftCarcassList(CarcassList); 
     AddCarcassesToSummaries(CarcassList, Full); 
     finally 
     CloseFiles; 
     end; 
     Where := 'Send'; 
     SendSummaries; 
     Where := 'Done'; 
    finally 
     FreeAndNil(CarcassList); 
     FSummaryListCS.Leave; 
    end; 
    except 
    on E: Exception do 
    begin 
     E.Message := 'Update(' + Where + '): ' + E.Message; 
     raise; 
    end; 
    end; 
end; 

從記錄我可以告訴When := 'WM_UPDATE';被擊中Where := 'GetList';不是。這導致我認爲在將Update()過程中的本地Where變量添加到堆棧時發生訪問衝突。

我可以添加哪些額外的診斷來幫助解決導致問題的原因?有什麼方法可以檢查堆棧是否損壞和/或將Where變量添加到堆棧?

我意識到這是一個相當模糊的問題,但我想不出任何可以嘗試縮小範圍的問題。

確切錯誤是:

異常(EAccessViolation)在摘要線程WM_UPDATE:訪問衝突在模塊地址004B6759 'Application.exe'。讀取地址00000008

+0

(1)確切的錯誤信息?(2)你確定線程對象是有效的並且沒有消失嗎? – JensG

+0

您如何知道訪問衝突正在發生?什麼是實際症狀/日誌?未能在堆棧上放置變量不會生成AV,並且將一個值(特別是文字)賦值給'String'並不會將該數據放在堆棧上。在這段代碼中沒有任何東西可以導致你聲稱的AV,除非AV是從RTL的內存管理器本身來的,在這種情況下你的應用程序被搞砸了,你需要重新啓動它。 –

+0

順便說一下,當涉及到跟蹤內存問題時,儘量減少內存分配,不要使用分配來跟蹤問題。使用['OutputDebugString()'](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363362.aspx)進行日誌記錄,並使用類似[DebugView]的工具(http:// technet .microsoft.com/en-us/sysinternals/bb896647.aspx)在IDE調試器外部運行應用程序時查看這些消息。 –

回答

2

在您的可執行文件的「項目選項」中,找到鏈接器設置。確保Map file設置配置爲Detailed。當您在鏈接器設置頁面上時,請檢查Image base地址。這很可能是$ 00400000,如果不寫就記得它的設置。

重建您的可執行文件(我假設您的項目是一個單一的可執行文件,它似乎基於您提供的例外文本)。在編譯器的輸出目錄中,您應該找到名爲「Application.map」的文件。用你最喜歡的文本編輯器打開這個文件。

現在,取出異常消息中報告的地址(本例中爲$ 004B6759)。從異常地址中減去可執行文件的基地址($ 00400000)。這給你$ B6759。減去1000美元(我敢肯定它是扣除的,如果不是有人會指出它應該添加在評論中)。留下$ B5759。這是發生訪問衝突的可執行文件內的偏移量。

使用先前加載的地圖文件,請查看Detailed map of segments部分。找到小於或等於$ B5759的第一個條目,緊接着一個大於$ B5759的分段。掃描與該段關聯的單元名稱(它是標有「M =」的單元名稱)。

在地圖文件中搜索單元名稱,您會找到一個標題爲「XXX(..)segment .text」的行號的部分,其中XXX是您正在查找的單元的名稱。在本節中將列出行號和該行號的第一個字節代碼的偏移量。找到小於或等於$ B5759的第一個行號(基於地址),緊接着大於$ B5759的偏移量。

這將告訴你包含實際導致訪問衝突的編譯代碼的行號(和源文件)。

正如其他人所說,鑑於例外是讀取$ 8,您可能試圖讀取一個零指針或對象..可能是記錄或對象的第二個字段(假設32位代碼)。

祝你好運。