以下代码似乎在我的计算机上运行正常,但却为客户提供了访问冲突。
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
答案 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位代码)。
祝你好运。