Как иногда пишутся программы
От: DarkMaster Украина http://www.bdslib.at.ua
Дата: 22.12.09 09:40
Оценка: 4 (1) -1
Привет всем.

Несколько дней назад попросили разобраться в коде некой программы (программа куплена с исходниками, даже есть некоторая поддержка со стороны разработчиков). Симптомы — запускаем программу, закрываем. ГУИ уходит, а вот программа остается висеть в памяти. И каждый новый запуск создает очередную копию, которая только из списка задач убивается .

Беру исходники, ProcessExplorer, компилирую, запускаю на тестовой системе — ОК. Закрываю. Запускаю еще раз — в ProcessExplorer — 2 копии программы. Еще раз запускаю — 3 копии.

Оказалось, что при закрытии определенного фрейма вылетает AV. Вот тут и начались чудеса. Разработчики видимо решили не пугать пользователя и вынесли закрытие фреймов в процедуру типа:

Procedure FreeFrame(AFrame:TFrame);
begin
  if Assigned(AFrame) then
    try
     FreeAndNil(AFrame)
    except end;           // <- фокус первый - тут всегда все тихо!
end;


Ладно, открываю проблемный фрейм и пробую закрыть — AV! Еще одна попытка — "Privileged instruction bla-bla". Интересно? Обычно AV он и в Африке AV — а тут без каких либо правок — 2 разных эксепшена + Call stack указывает в небо. Идем дальше — анализируем деструкторы фреймов — ВСЕ ПРАВИЛЬНО . Все действительно корректно и должно разрушаться нормально. 2 часа дебага — и ничего — все корректно разрушается, но при закрытии фрейма всегда AV. И тут (в 2 часа ночи!) потянуло меня посмотреть, каким же образом фрейм этот создается...
Код был примерно такой:

 case AFrameType of
   fTypeOne :  Frame:=TOneFrame.Create(...);
   fTypeTwo :  Frame:=TTwoFrame.Create(...);
   .....
   else : Frame:=TBaseTypeFrame.Create(...) ;  // <- фокус второй - а давай-те хоть что-нить создадим, а?
 end;


и далее:

 case AFrameType of
   ......
   fTypeNNN : TNNNFrame(Frame).SubFrame:=TSubFrame.Create(...);  // уже догадались? Тут псевдокод, в реальном проекте тут разные свойства выставлялись.
   ...... 
 end;


Так вот, разработчики в первом case (создания фреймов) пропустили один из fTypeХХХХ и создали какой-то свой базовый фрейм. СПАСИБО! Ну кто мешал в nil выставить? Во втором case они этот fTypeXXXX не забыли и благодаря приведению типов смогли угнездить туда (ага, именно куда-то туда — где-то рядышком) еще один фрейм, который нормально работал. До попытки закрытия При закрытии деструктор лез непонятно куда и пытался что-то разрушить. Ну а благодаря некоторым манипуляциям вроде первой приведенной процедуры программа просто не могла нормально завершить свою работу.

Вывод — если уж пользуетесь приведением типов — делайте это в презервативе...

P.S. Процедуру создания фреймов я исправил, разработчиков известил (ну нет у меня времени выискивать все их пасхальные яйца). Жду новых оригинальных решений.
WBR, Dmitry Beloshistov AKA [-=BDS=-]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.