четверг, 15 июля 2010 г.

[prog.memories] 3-я часть пути к отладчику, с отладчиком и…

Продолжение (первая и вторая части).

Первый опыт программирования под Windows сумел слегка нарушить зависимость от отладчика, приобретенную за время работы под MS-DOS-ом. Хотя, в последствии, удалось перебраться на более мощные компьютеры, где можно было уже вести всю разработку прямо в Windows (тогда это была Windows 3.11). Но асинхронная природа Windows-приложений, написанных на голом WinAPI, все равно существенно снижала ценность отладчика.

Время шло, где-то в 1995-м стало понятно, что 16-ти битовый Windows 3.11 – это уже вчерашний день. Будущее было за 32-х битовыми версиями Windows. И мы начали потихоньку к этому делу готовиться. Сначала с помощью Win32s, затем с первыми публичными beta-версиями Windows 95 и, наконец, с Windows NT 3.5. В составе Borland-овских компиляторов (вроде бы, начиная с версии 3.1) был отдельный 32-х битовый отладчик TDW32. Я не помню, чтобы приходилось им часто пользоваться – вроде бы связка из Win32s и TDW32 была не очень надежной и стабильной вещью.

Стоило нам добраться до настоящего Win32 (под Windows 95 и Windows NT 3.5/3.51), как захотелось познакомиться с многопоточностью. Казалось, что это сложно :) Но я ошибался. Написать многопоточное приложение для Win32 оказалось не сложно. Сложно было его отлаживать. Режим пошаговой отладки, к которому я привык в MS-DOS, в многопоточной программе был бесполезен в принципе. Ну то есть вообще.

Сейчас я не могу сказать, помогал ли TDW32 в то время хотя бы обнаружить место возникновения тупика. По-моему, нет. Это сейчас в Visual Studio отладчиком можно прервать все потоки подвисшего приложения и посмотреть места, на которых остановилась каждая из нитей (таким образом хотя бы можно место тупика). А тогда этого, насколько я помню, вообще не было. Не говоря уже о том, что отладчик был бесполезен в определении гонок и взаимной модификации незащищенных разделяемых данных.

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

В 1995-1999 годах я работал в двух местах одновременно. На первом месте работы я программировал под Windows. А вот на втором месте – под OS/2. Отличная была система. По надежности, отзывчивости и ресурсоемкости давала фору всем тогдашним Windows-ам. Только вот с софтом для OS/2 было гораздо хуже. В нашем распоряжении был какой-то Borland-овский C++ный компилятор под OS/2 и Borland-овский же отладчик. Так вот, этот отладчик был единственной полуосной программой, которая умудрялась повесить OS/2. Никто это не мог сделать, а вот Borland-овский отладчик мог. Причем в совершенно случайных местах. Можно было пять раз подряд загрузить в него одну и ту же программу и протрассировать один и тот же фрагмент кода. А на шестой точно такой же операции отладчик подвешивал всю систему. Или не на шестой, а на шестнадцатой. Или на первой.

Плюс к тому, в OS/2 были свои специфические ошибки, которые сильно портили кровь, но обнаружить которые с помощью отладчика не удавалось. Например, когда в Presentation Manager создавалось фреймовое окно (с заголовком, меню и рамкой), то требовалось, чтобы в ресурсах приложения была иконка с точно таким же идентификатором ресурсов, как и меню. Забыл добавить в ресурсы иконку – окно не создавалось. Пытаешься прогнать свой код под отладчиком, видишь ошибочный код возврата от PM-ной функции, но понять, чего PM-у не хватает, не можешь.

Затем мы вообще, если не ошибаюсь, перешли с Borland-овского компилятора на Watcom-овский. В котором отладчика под OS/2 не было вовсе (по крайней мере в нашем дистрибутиве Watcom 11). Так что году в 1997-м произошел откат к методике разработки под Robotron 1715 – компилятор есть, а отладчика нет :) Хотя к тому времени это уже вообще не было проблемой. Поскольку к этому времени я уже познакомился с Linux-ом и начал работать не просто с многопоточными, а многопроцессовыми приложениями…

Продолжение следует.

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