行之间的访问冲突

时间:2014-06-23 22:51:52

标签: delphi stack delphi-5

以下代码似乎在我的计算机上运行正常,但却为客户提供了访问冲突。

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';没有被点击。这使我认为当Where过程中的本地Update()变量被添加到堆栈时发生访问冲突。

我可以添加哪些额外的诊断信息来帮助解决造成问题的原因?有什么方法可以检查堆栈是否已损坏和/或堆栈中添加了Where变量?

我意识到这是一个相当含糊的问题,但我想不出任何可以尝试缩小范围的事情。

确切错误是:

  

WM_UPDATE摘要线程中的异常(EAccessViolation):模块' Application.exe'中地址为004B6759的访问冲突。读取地址00000008

1 个答案:

答案 0 :(得分: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美元的读数,你可能试图从nil指针或对象读取..可能是记录或对象的第二个字段(假设是32位代码)。

祝你好运。