Недавно был случай: у клиента при запуске программы возник загадочный Access Violation, а проблема оказалась в статически прилинкованной Dll-ке. Но начав исследовать эту проблему, выявился большой комок ужасного кода.
Звонит коллега: я у клиента, поставил обновление, и последний билд не запускается на 3х компах из 10. При старте программы вылетает сообщение об ошибке по адресу 0x0000L0L0. А очень старый билд запускается без проблем. Подключись пожалуйста удалённо, говорит, и посмотри в чём может быть дело.
Дело осложнялось тем, что даже при запуске проги в режиме отладки log оставался пустым. Значит ошибка происходила до запуска системы логирования, скорее всего в initialization секции какого-то юнита. Расставил во всех initialization секциях основных модулей показ диалогов с сообщениями, чтобы понять в чём проблема. Сделал билд, подключился. Запускаю - тот же эффект, моих сообщений нет, сразу же Access Violation.
Решил посмотреть при обращении к каким файлам происходит сбой. Скачал и запустил Process Monitor. Программа вылетает после обращения к gds32.dll (клиентская библиотека Firebird). Dll-ка лежит рядом с exe, версия последняя - всё как надо.
Ещё раз сам проверяю очень старый билд - тот запускается без проблем.
А тут надо заметить, что очень старый билд лежал в папке c:\MyProgram, а новый билд был в папке c:\MyProgram\NewBuild. Названия папок конечно были другие, но иерархия та же. Скопировал я exe от очень старого билда в папку к новому, и опа - тоже вылетает. А если последний билд перенести в c:\MyProgram то он запускается нормально. А когда-то, после пары случаев поиска неисправной DLL-ки я добавил в программу возможность посмотреть пути до всех используемых файлов и их версий (dll-ок, конфигов и т.п.). Выяснилось, что при запуске из c:\MyProgram используется gds32.dll версии 0.9, и с ним всё работает. А если брать последнюю gds32 - то ошибка. Знатоки Firebird тут воскликнут, а клиент Firebird был установлен? И будут трижды правы, клиента никто не ставил, новую gds32.dll просто скопировали.
В общем, проблема решилась после установки Microsoft Visual C++ Redistributable Package. Видимо последний клиент использовал более новую версию MSVCRP.
Коллега сказал спасибо, и я стал думать почему так произошло. В программе используются FibPlus и IBX компоненты. Fib-ы насколько я помню, загружают клиента БД динамически, а вот насчёт IBX-ов я не был уверен. Проверил, оказалось что и Fib-ы и IBX-ы тут не причём. Поискал у себя в программе - и обнаружил 2 external функции, ссылающиеся на gds32.dll в самой программе, и ещё целый юнит в отдельном пэкэдже, статически привязывающий кучу функций из gds32.dll. Я не знаю кто был тот программист, который писал этот юнит, как и не знаю то зачем он это делал, но видимо человек решил написать свою собственную прослойку для работы с БД. Часть из этих функций вызывалась из потоков, и при проверке генерировала свои собственные ошибки. В старых версиях FB клиента для каждого потока нужно было создавать отдельный коннект а БД, а те потоки пытались использовать один. В клиенте от версии 2.5, эта часть вроде переделана. В общем, чем разбираться в Firebird API, я решил переписать код потоков на использования компонентов (были выбраны IBX-ы, так как имеющаяся у меня версия FIB-ов имела свои проблемы с мнопоточностью. Я уже сталкивался с этим при написании тестировщика UDF-ок).
В общем, несмотря на то, что у клиента эта ошибка была устранена в течение часа, работа над кодом, не допускающим повторного возникновения той же ошибки затянулась на большее время. Часть статически прилинкованных функций была переписана для использования динамической загрузки. Часть кода, используемая в потоках была переписана ч использованием IBX-ов. А другая часть функций, как выяснилось вообще нигде не использовалась и была удалена.
Спонсор поста:
Агентство интернет-рекламы "Идеал" предоставляет следующие услуги: разработка и продвижение сайта, а также различные виды рекламы.
ля такого тестировщика UDF-ок вроде вообще не нужны Data-aware компоненты на формах.
ОтветитьУдалитьПочему бы просто не использовать UIB ? :-)
http://www.progdigy.com/?page_id=5
На формах не нужны, но ведь как-то же с базой данных нужно связываться. =)
ОтветитьУдалитьUIB не используются ни в одном из моих проектов, и мне не хотелось добавлять новые компоненты только ради одного тестировщика, тем более что IBX-ы вполне прилично работают в многопоточном окружении.
Кстати, UIB сейчас включены в состав JVCL.
>> При старте программы вылетает сообщение об ошибке по адресу 0x0000L0L0
ОтветитьУдалитьМожет я чего и не понял, но как можеть быть такой адрес?
>> При старте программы вылетает сообщение об ошибке по адресу 0x0000L0L0
ОтветитьУдалить> Может я чего и не понял, но как можеть быть такой адрес
Не может быть такого адреса. Это просто набор символов. Типа шутка такая. =) Реального текста ошибки и адреса я не помню.
:D Я то думал, что отстаю от современных технологий ))) Шучу конечно )
ОтветитьУдалить