Возможно ли, что FastMM неправильно сообщает о нарушении прав доступа? - PullRequest
5 голосов
/ 21 марта 2011

У меня есть сложное приложение, которое работает, как и ожидалось, при обычной компиляции, но закрытие формы приводит к нарушению доступа при компиляции с использованием FastMM 4.97 (последняя версия).AV происходит, когда отправка сообщения пытается обработать сообщение, предназначенное для кнопки в форме, которая уже была уничтожена.У меня также есть Eurekalog 6.1.0.1 (самый последний) для проекта.Он не перехватывает какие-либо исключения во время выполнения, когда этот же код выполняется с отключенным режимом FullDebug FastMM.

Возможно ли, что в некоторых ситуациях FastMM может изменить поведение EXE так, что оно вызывает, или ложносообщает о нарушениях прав доступа?

Вот отчет об ошибке FastMM:

--------------------------------2011/3/21 13:30:17--------------------------------
FastMM has detected an attempt to call a virtual method on a freed object. An access violation will now be raised in order to abort the current operation.

Freed object class: TftGenericButton80

Virtual method: Offset +80

Virtual method address: 4A1FF0

The allocation number was: 5628628

The object was allocated by thread 0xE80, and the stack trace (return addresses) at the time was:
403110 [System][@GetMem]
404F03 [System][TObject.NewInstance]
42E85D [FastMM4][CreateComponent]
42EAD9 [FastMM4][TReader.ReadComponent]
42FEE1 [Classes][TReader.ReadValue]
42ED86 [FastMM4][TReader.ReadDataInner]
42ECC5 [FastMM4][TReader.ReadData]
433802 [Classes][TComponent.ReadState]
4A21CE [Controls][TControl.ReadState]
4A5742 [Controls][TWinControl.ReadState]
48BCA0 [Forms][TCustomForm.ReadState]

The object was subsequently freed by thread 0xE80, and the stack trace (return addresses) at the time was:
40313B [System][@FreeMem]
404F21 [System][TObject.FreeInstance]
405339 [System][@ClassDestroy]
8AFBEF [..\..\AdvShapeButton.pas][AdvShapeButton][TAdvCustomShapeButton.Destroy][1422]
4A5601 [Controls][TWinControl.Destroy]
48A9DD [Forms][TScrollingWinControl.Destroy]
48B9D8 [Forms][TCustomForm.Destroy]
48B9F2 [Forms][TCustomForm.Destroy]
404F67 [System][TObject.Free]
A9C42C [..\..\fmWaitingList.pas][fmWaitingList][TfrmWaitingList.OnTanWaitingListItem][130]
A9D41B [fmWaitingListItem.pas][fmWaitingListItem][TfrmWaitingListItem.DoOnTanItem][142]

The current thread ID is 0xE80, and the stack trace (return addresses) leading to this error is:
8B2630 [..\..\AdvShapeButton.pas][AdvShapeButton][TAdvCustomShapeButton.Click][3042]
4A4817 [Controls][TControl.WMLButtonUp]
4A4227 [Controls][TControl.WndProc]
7E42B401 [CallNextHookEx]
7E42B401 [CallNextHookEx]
7E42B372 [MoveWindow]
7E42B317 [MoveWindow]
7E42B326 [MoveWindow]
7E42B326 [MoveWindow]
7E4278D0 [GetWindowTextLengthW]
7E4278E0 [GetWindowTextLengthW]

Current memory dump of 256 bytes starting at pointer address 7FEB5F00:
90 8C AD 00 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80
  Œ  ­  .  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €
€  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €  €

Ответы [ 3 ]

13 голосов
/ 21 марта 2011

Это не сообщение AV; создает фальшивое исключение AV для того, чтобы остановить ваш процесс, потому что дорога к нему - доступ к удаленному объекту - часто приводит к повреждению данных, что еще хуже.

Проблема не в нарушении прав доступа;проблема в том, что кто-то пытается вызвать метод Click для кнопки, которая уже была освобождена.Просто глядя на эту трассировку стека, кажется, что у вас или у кого-то еще есть установленный хук, который содержит ссылку на кнопку и не обновляется соответствующим образом после уничтожения формы.Вот где бы я начал искать.

7 голосов
/ 21 марта 2011

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

Хорошим местом для начала проверки должен быть метод, в настоящее время подключенный к событию TfrmWaitingList.OnTanWaitingListItem.

Вы сказали, что это происходит при закрытии формы.
Я предполагаю, что ваша форма уничтожается (а не просто скрывается) при закрытии, поэтому она в свою очередь уничтожит все объекты, принадлежащие этой форме.

Как закрывается форма? Вы можете рассмотреть Form.Release вместо этого.

2 голосов
/ 21 марта 2011

Я считаю, что FastMM чрезвычайно надежен в этом отношении.

Если вы работаете в режиме выпуска, у вас не будет проблем с вызовом методов для освобожденных объектов в 99,9% случаев. 0,1% времени всегда будет происходить только на вашем самом ценном клиентском компьютере!

Итак, я бы поспорил, что это проблема. На самом деле это довольно легко отследить, потому что FastMM предоставляет вам все стеки вызовов, которые точно показывают, как это произошло. Вам просто нужно тщательно продумать детали.


Теперь вы можете спросить, как я могу вызвать метод для объекта, который был освобожден? Хорошо, когда вы освобождаете объект, вы возвращаете память диспетчеру памяти. Но диспетчер памяти обычно удерживает эту память и ждет подходящего момента для ее повторного использования. Важно, что он не сразу возвращает его в систему, потому что это дорого (это занимает значительное время).

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

Это одна из лучших функций FastMM, на мой взгляд, и соблюдение этого предупреждения избавит вас от боли в будущем. Попытка отследить такую ​​проблему на поле чрезвычайно трудна. Исправить это с помощью информации, предоставленной FastMM, обычно просто.

...