Следующий код работает нормально на моем компьютере, но дает нарушение прав доступа для клиента.
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
?
Я понимаю, что это довольно расплывчатый вопрос, но я не могу придумать ничего, чтобы попытаться его сузить.
Точная ошибка:
Исключение (EAccessViolation) в сводной ветке на WM_UPDATE: нарушение прав доступа по адресу 004B6759 в модуле «Application.exe». Чтение адреса 00000008
String
в любом случае не помещает эти данные в стек. В этом коде нет ничего, что могло бы вызвать AV, если вы утверждаете, что AV исходит от самого диспетчера памяти RTL, и в этом случае ваше приложение облажалось, и вам нужно перезапустить его. - person Remy Lebeau   schedule 24.06.2014OutputDebugString()
для ведения журнала и используйте такой инструмент, как DebugView, чтобы увидеть эти сообщения, когда вы запускаете приложение за пределами отладчик IDE. - person Remy Lebeau   schedule 24.06.2014nil
. Единственное место, где показанный вами код обращается к любому такому указателю, - это вызовUpdate()
через указательSelf
, который сам по себе не вызовет AV до тех пор, покаUpdate()
не попытается получить доступ к члену класса, или если самUpdate()
является виртуальным и, следовательно, опирается на vtable вызываемого объекта. - person Remy Lebeau   schedule 24.06.2014'Update('+Where+')'
кE.Message
, поэтому AV не может происходить внутри блокаtry
, который вы показали дляUpdate()
, он должен происходить где-то еще. Если не произойдет сбой самого prepend, что восходит к возможности повреждения диспетчера памяти RTL. Если бы это происходило, вы могли бы повредить случайную память в любое время из любого места кода, иUpdate()
был бы просто ничего не подозревающей жертвой, если бы ему довелось получить доступ к поврежденной памяти. Это гораздо более редкая возможность, и ее гораздо сложнее диагностировать и исправить, если она случайная. - person Remy Lebeau   schedule 24.06.2014When := 'WM_UPDATE';
и строкойUpdate(False)'
ничего нет. После него тоже ничего нет, кроме блокаtry
. - person energ1ser   schedule 24.06.2014try
внутриUpdate()
- прологи настраивают фрейм стека и фрейм обработчика исключений. Ни чего не может скинуть AV. И вы не ответили на вопрос Дэвида о том, откуда на самом деле беретсяTMsg
. ЭтоWindowProc
? Обработчик событийOnMessage
? Обработчикmessage
? Вам нужно предоставить больше контекстной информации, если вы ожидаете, что люди будут помогать в дальнейшем. В нынешнем виде код, который вы показали, НЕ диагностируется как есть. - person Remy Lebeau   schedule 24.06.2014self
- ЕДИНСТВЕННЫЙ кандидат. - person Hugh Jones   schedule 24.06.2014Self
. Вот почему я задал вопрос (2) выше. - person JensG   schedule 24.06.2014When
просто содержит значение из предыдущей итерации и неточно отражает когда возникает ошибка. - person Disillusioned   schedule 24.06.2014