Приплюснутый

На работе довелось возиться с новым куском проекта. Для меня новым, а без меня он уже много лет существует. На этот раз – Си++. Но мощь языка Си++, как известно, искупается возможностью свить из него веревку достаточной длины чтобы застрелиться. И ориентация во всех этих незнакомых классах, методах и полях – задача весьма трудная. Кто делает проекты только для Windows, тот этой проблемы не осознает в полной мере – в Visual Studio есть прекрасный навигатор по исходникам и мощный отладчик. Главное – изначально скомпилировать проект. Впрочем, пользователи Builder C++ тоже не обделены автоподстановкой и прочей роскошью. Но теперь мы переходим к беднягам-гикам, которые в силу личных убеждений или жизненных обстоятельств, пишут проекты под Linux или мультиплатформенные. Что? Оказывается нас много? Ну, тогда вот мои три копейки.


Для начала работаем с исходниками. Сейчас есть KDevelop и Eclipse с радостями, которые раньше были доступны только заоконным жителям. Одна беда – на моей рабочей машине поставить последние, уже работающие, версии не получается. Но не будем грустить – будем работать со старыми, проверенными инструментами.

Для ориентации в исходных текстах Си был придуман ctags. Потом он стал поддерживать множество других языков, но о них не пойдет речь в нашей саге. ctags проходит по всем указанным файлам, распознает их тип и строит табличку – какое определение в каком файле. Для чистого Си это идеальное средство. В Си++ начинаются проблемы при наследовании, перегрузке, одном имени для методов в разных классах (например, у меня сейчас более 30 методов printOn). Но я не первый, кто сталкивается с такой проблемой. ctags умеет добавлять имя класса к имени метода. Надо только нужный ключик указать: ctags -R –extra=+q. Теперь он пройдет по всем поддиректориям и соберет информацию обо всех файлах на Си, Си++, Перле, Фортране и т.д и т.п. Стоит отметить, что эти исходники могут и не компилироваться в данный момент. Эта даже может быть только ветка большого проекта, не так уж это страшно.

Но куда, спросите вы, это нужно прикручивать? А я вам отвечу – к хорошему редактору. Какой из них хороший? А я вам опять отвечу – тот который вам нравится. Ну и, конечно, имеет подсветку синтаксиса, макросы, автозамены, развитый поиск и замену. А еще умеет ходить по индексам. Я, например, пользуюсь vim. Можно emacs, Nedit, FTE, jed, UltraEdit, X2, Zeus, но о них не пойдет речь… И теперь, запустив редактор и указав где брать файл tags, можно сказать, что мне нужен метод printOn из класса myClass. Для этого в vim надо набрать :tj myClass::printOn.

Ходим, правим, компилируем.

Но вот, наконец, программа скомпилирована и запущена. Но ведет себя не так как хотелось. Тут, конечно, нужен отладчик. Под Linux gdb разумеется (для эстетов помянем Sun’овский dbx, но о нем не пойдет…). Есть у gdb большой минус – не показывает он исходники по ходу отладки, постоянно нужно команду l использовать. Можно, конечно, запустить ddd и чувствовать себя почти как белый человек – красивые окошки, графический интерфейс. Но это не наш метод, особенно когда ddd запускается пять минут и падает через раз. И я уже и не говорю про работу на американских серверах, с задержками ответа на каждое нажатие по секунде. Видно, опять не я первый хочу странного и, начиная с версии 6.4, gdb умеет показывать текстовое окно с исходниками (see TUI). Магическая команда winh src 20 и получаем 20-ти строковое окно в верхней части терминала. Главное – сразу нажать Ctrl-x o, а то верхнее окно будет активным и многие клавиши в командной строке gdb работать не будут. Вернее будут, но с верхним окном.

Для начала надо добраться до подозрительного места, то есть поставить точку останова и запустить. И тут мы опять упираемся в перегрузку, наследование, методы с одним именем в десяти разных классах. И простое break printOn понято не будет. Можно искать в исходниках, а потом указывать файл и номер строки, ведь не зря же мы прикрутили классы к редактору. Но, поверьте, неудобно. Выход есть! Пишем имя класса, через двоеточие – имя метода, все стандартно. НО! Перед именем класса ставим одинарную кавычку . А в любой момент набора нажимаем Tab для автодополнения. И умный gdb полностью декорирует имя, с классом и типами аргументов.

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