2013-10-25 2 views
1

У нас есть приложение Delphi, которое работает в течение нескольких лет, и теперь мы внезапно получаем странные нарушения доступа. Мы использовали Eurekalog, чтобы проследить, откуда он, и это еще более странно. Они до сих пор находятся на свободном вызове объекта, но внутри try, кроме блока. Один из них даже в 2 попытках, кроме блоков, и все же, когда происходит нарушение доступа, он полностью выпрыгивает из программы и игнорирует исключение try, ничего, кроме EurekaLog, ловит его в конце. На самом деле это путают, почему это внезапно происходит (оба экземпляра - это старый код, который не затрагивался годами, а также другие изменения кода не связаны с ним).Не удается получить нарушение доступа

Пример из кода является

 try 
    if Assigned(ClientCommunication) then begin 
     if ClientCommunication.isConnected then begin 
     if ClientCommunication.closeServerConnection then begin 
      try 
      ClientCommunication.Free; 
      ClientCommunication := nil; 
      Except 
      on e:Exception do begin 
      ClientCommunication := nil; //suppress weird AV error.. get read for new object 
      end 
      end; 

Теперь последняя попытка только была добавлена ​​позже, чтобы попытаться подавить AV, как мы просто хотим, чтобы объект очищенную должен быть перезапущен, если это необходимо, но это в основном вызывается, когда закрытие приложения. Но он все еще просто выскакивает из этого, и я не могу его поймать.

Он работает на наших компьютерах разработчиков, а не у клиента.

+3

Пахнет кучей коррупции. Решение будет включать отладку. Только ты можешь это сделать. –

+0

_Heap crime_, скорее всего, случай, но я могу представить, что метод '.closeServerConnection()' уничтожает родительский объект объекта ClientCommunication (через обратный вызов или некоторую акробатику указателя), поэтому любая попытка доступа к нему может легко привести к AV-ошибке. В любом случае вы можете попытаться отладить проблему, добавив часы к «ClientCommunication» и ее родительскому объекту, затем выполните код по очереди и посмотрите, куда были выпущены указатели. ** Ошибка, очевидно, не в коде, показанном выше. ** – mg30rg

+0

Я сделал этот тип отладки, проблема заключается в том, что родитель фактически не освобождается нигде внутри закрытия. Он просто отправляет команду закрытия на сервер и закрывает соединение. Вот почему это очень странно. Но если куча коррупции, то действительно странно. Посмотрите, что я могу сделать, добавив FastMM4 сейчас, чтобы попытаться выяснить, может ли он каким-то образом осветить проблему. – Johannes

ответ

1

Если эта строка: ClientCommunication.Free; вызывает исключение. Здесь вы можете сделать несколько вещей.

FreeAndNil
Заменить вызовы AObject.free с вызовами freeandnil(AObject).
Если вы просто сделаете бесплатный, старый указатель будет по-прежнему иметь ссылку, отличную от нуля, и Assigned(AObject) не сможет рассказать об освобожденном и активном объекте.

Остерегайтесь клонов
Другая ошибка, которую вы можете сделать то, что вы клонировали объект так:

Object1:= TObject1.Create; 
//.... lots of code 
Object2:= Object1; 
//.... lots of code 
FreeAndNil(Object2); <<-- freeing the clone-reference is a mistake 
//.... lots of code 
Object1.Free; <<-- exception: it's already freed 

вариантов FastMM4
Скачать последнюю FastMM4 из http://sourceforge.net/projects/fastmm/
Он имеет несколько дополнительных колоколов и свистков из того, что включено в Delphi. (*)
Среди этих свистов - дополнительный диагностический режим, который делает лет Ур медленнее, но также вылавливает много ошибок, связанных с коррупцией в куче, с которой вы, похоже, страдаете.

Открывает defines.inc и изменить:

{$ifdef DEBUG} 
    {.$define EnableMemoryLeakReporting} 
    {.$define FullDebugMode} 
    {.$define RawStackTraces} 
{$endif DEBUG} 

В этом

{$ifdef DEBUG} 
    {$define EnableMemoryLeakReporting} 
    {$define FullDebugMode} 
    {$define RawStackTraces} 
    {$define CatchUseOfFreedInterfaces} <<-- very useful 
    {$define LogMemoryLeakDetailToFile} 
    {$define LogErrorsToFile} 
    {$define CheckHeapForCorruption} <<-- :-) 
{$endif} 

Там хорошая статья здесь: http://wiert.me/2009/07/29/delphi-fastmm-using-fastmm4-for-debugging-your-memory-allocations-part-1-introduction/
Если вы не чувствуете, как отвод о с файлом ИНК, там небольшая утилита, которая сделает это за вас по адресу: http://jedqc.blogspot.com/2007/07/new-fastmm4-options-interface.html

(*) Я думаю, что у Delphi есть и большинство отладочных вещей, но не на 100% уверен. Несмотря на это, не может повредить, чтобы получить последнюю (самую большую) версию.

Или переполнение буфера
Если ClientCommunication объект имеет некоторую внутреннюю структуру бесплатно будет делать дополнительную работу.

Представьте себе следующий код:

TUnrelatedObject = class 
    buffer: array[0..99] of integer; 
    procedure DoWork; 
end; 

TUnrelatedObject.DoWork; 
var 
    i: integer; 
begin 
    for i:= 0 to 100 do buffer[i]:= maxint; <<-- buffer overrun 
end; 

Представьте себе, что ClientCommunication находится прямо рядом с UnrelatedObject в куче.
Звонок DoWork также перезапишет данные ClientCommunication.
Это может вызвать или не вызвать нарушение доступа в DoWork. Если этого не произойдет, ошибка будет очень трудной для отслеживания, потому что она будет отображаться в разных и совершенно несвязанных местах.

Включить проверку диапазона {$R+} в вашем приложении.

Предупреждение
Помните не корабль отладочную версию для ваших клиентов.
Со всей отладкой ваша программа будет медленной.

+0

Спасибо, что все это действительно помогает. Поработайте над этим, но я верю, что со всей этой информацией мы наверняка доберемся до того места, которое создает наши проблемы. Спасибо за ваше время и усилия в этом ответе. – Johannes

+0

просто хочу сказать спасибо. настройки помогли много, и с более отладочной информацией и протоколированием я в конце концов обнаружил проблему с указателем, и это, казалось, стало причиной неясных ошибок. Теперь все снова работает отлично. Спасибо. – Johannes

Смежные вопросы