【发布时间】:2014-06-24 14:02:44
【问题描述】:
以下代码在我的机器上似乎可以正常工作,但会导致客户访问冲突。
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 变量被添加到堆栈的位置?
我意识到这是一个相当模糊的问题,但我想不出任何办法来缩小范围。
确切的错误是:
WM_UPDATE 的摘要线程中的异常 (EAccessViolation):模块“Application.exe”中地址 004B6759 的访问冲突。读取地址 00000008
【问题讨论】:
-
(1) 确切的错误信息? (2) 你确定线程对象是有效的并且还没有消失吗?
-
您如何知道发生了访问冲突?实际的症状/日志是什么?未能将变量放入堆栈不会生成 AV,并且将值(尤其是文字)分配给
String无论如何都不会将该数据放入堆栈。这段代码中没有任何内容会导致您声明的 AV,除非 AV 来自 RTL 的内存管理器本身,在这种情况下,您的应用程序被搞砸了,您需要重新启动它。 -
顺便说一句,在跟踪内存问题时,尽量减少内存分配,不要使用分配来跟踪问题。使用
OutputDebugString()进行日志记录,并使用DebugView 之类的工具在IDE 调试器之外运行应用程序时查看这些消息。 -
@JensG 我已经添加了确切的错误消息。上面的代码来自 TSummaryThread.Execute 方法,所以我认为线程对象仍然有效。
-
把 madexcept 放在这个过程中并获得一些真实的信息。看起来像一个零对象。也许 self 为零。