пятница, 25 сентября 2009 г.

Интерфейсы должны быть интерфейсами!

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

Есть объект, унаследованный от TComponent и поддерживающий какой-то интерфейс. Временем жизни этого объекта управляет некая фабрика, честно убивающая его при закрытии приложения вручную, как обычный объект - т.е. посредством вызова Free.

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

А при завершении работы - фабрика все честно чистит и умирает сама, выполняется весь пользовательский код. И начинают финализироваться модули, обнуляя интерфейсы и соотв. дергая TComponent._Release у давно умершего объекта...

Обнаружить сию неприятность удалось только благодаря FastMM, который заполняет память под разрушенными объектами по специфическому шаблону:

Q: My program used to work fine, but if I enable "FullDebugMode" and run it I get an access violation at address $8080xxxx. Why?
A: You are attempting to access properties of a freed object. When you free a block in "FullDebugMode", FastMM fills the freed memory area with a pattern of $80 bytes. If there were any pointers, long strings or object references inside the freed object they will now point to $80808080 which is in a reserved address space.

Комментариев нет: