29 ноября 2010 г.

Цитата: Резерфорд

Однажды вечером нобелевский лауреат и гениальный физик Резерфорд зашел в лабораторию. Хотя время было позднее, в лаборатории склонился над приборами один из его учеников.
— Что вы делаете так поздно? — спросил Резерфорд.
— Работаю, — последовал ответ.
— А что вы делаете днем?
— Работаю, разумеется, — отвечал ученик.
— И рано утром тоже работаете?
— Да, профессор, и утром работаю, — подтвердил ученик, рассчитывая на похвалу.
Резерфорд помрачнел и раздраженно спросил: — Послушайте, а когда же вы думаете?
Из юмористических баек
о жизни известных физиков

26 ноября 2010 г.

Clang API: получение AST в виде XML


Задача: с помощью Clang API получить XML-файл, описывающий абстрактное синтаксическое дерево (AST) исходного кода. Это можно сделать и простым запуском команды clang с параметром -ast-print-xml в командной строке, но через API — интереснее :)

24 ноября 2010 г.

Исключения C++ и производительность (2)

Предыдущее: Исключения C++ и производительность (1.1)

Итак, я знаю, что в общем случае при обработке сгенерированного исключения происходят дополнительные затраты процессорного времени. Какие они и чем мне это грозит?

23 ноября 2010 г.

Исключения C++ и производительность (1.1)

Предыдущее: Исключения C++ и производительность (1)

Наверное, нужно упомянуть предстоящие изменения в стандарте C++. Херб Саттер, который уже лет десять пытается бороться со спецификаторами throw(), все-таки добился того, чтобы в новом стандарте спецификаторы throw(A, B, ...) считались устаревшими, а спецификаторы throw() были заменены на новый спецификатор noexcept именно с той целью, чтобы компиляторы могли выполнять оптимизацию, если возможно.

Лично я считаю, что как спецификатор не назови (throw или noexcept), то компилятору всё равно. Для программиста — да, noexcept куда более читабельно, но смысл при этом не меняется.

Что касается спецификаторов throw(A, B, ...), то если их все-таки упразднят в окончательной версии стандарта — то и бог с ними, если нет — тоже не страшно. Но мне интересно почему спецификаторы throw(A, B, ...) не использовались для углубленного статического анализа кода компиляторами, это ведь было возможно?.. Вместо того, чтобы их ругать, их можно было превратить в оружие. Ну да ладно, до принятия нового стандарта еще дожить надо :)

Продолжение: Исключения C++ и производительность (2)

22 ноября 2010 г.

Проблемы линковки библиотек clang и llvm

При линковке приложения с библиотеками clang и llvm может возникнуть такая проблема, что нужно передавать линковщику список библиотек в строгом порядке, иначе может возникнуть ошибка "undefined reference" даже если нужная библиотека указана в параметрах линковки. (Как здесь, например. Правда, там у человека еще и строка линковки некорректна.)

Пример:

$ g++ -o ./a.out main.o `llvm-config --ldflags` -lclangFrontend -lclangBasic -lclangDriver -lclangSerialization -lclangCodeGen -lclangSema -lclangChecker -lclangAnalysis -lclangIndex -lclangRewrite -lclangAST -lclangParse -lclangLex `llvm-config --libs`

libclangParse.a(Parser.o): In function `clang::Parser::ExpectAndConsume(clang::tok::TokenKind, unsigned int, char const*, clang::tok::TokenKind)':
Parser.cpp:151: undefined reference to `clang::tok::getTokenSimpleSpelling(clang::tok::TokenKind)'
libclangLex.a(Preprocessor.o): In function `clang::Preprocessor::DumpToken(clang::Token const&, bool) const':
Preprocessor.cpp:155: undefined reference to `clang::tok::getTokenName(clang::tok::TokenKind)'
collect2: ld returned 1 exit status



Все нужные библиотеки указаны, но не в том порядке, в каком хотелось бы линковщику. Проблема в том, что линковщик ищет в каждой библиотеке по одному разу и именно в том порядке, в каком они указаны в командной строке. Например, символ clang::tok::getTokenName находится в библиотеке libclangBasic.a, которая в списке линковки указана раньше.

Можно попытаться поискать правильный порядок (долгая и неблагодарная работа), а можно воспользоваться возможностью группировки библиотек:

$ g++ -o ./a.out ../build/obj/testclang.o `llvm-config --ldflags` -lgtest -lgtest_main -Wl,--start-group -lclangFrontend -lclangBasic -lclangDriver -lclangSerialization -lclangCodeGen -lclangSema -lclangChecker -lclangAnalysis -lclangIndex -lclangRewrite -lclangAST -lclangParse -lclangLex `llvm-config --libs` -Wl,--end-group

Линковщик будет перебирать библиотеки, указанные между ключами --start-group и --end-group снова и снова, пока не отыщет все требуемые символы.

Теперь всё ОК.

18 ноября 2010 г.

Цитата: Бек

У программиста во время работы появляется соблазн думать только о компьютере. Однако во время программирования стоит подумать и о других людях.

Кент Бек, "Шаблоны реализации
корпоративных приложений"

16 ноября 2010 г.

Исключения C++ и производительность (1)

Существует очень много книг с советами, как лучше программировать на С++, и все они рекомендуют использовать исключения C++ для обработки ошибок. Возможно, есть книги, в которых не рекомендуется использовать исключения, но я таких не встречал. Сейчас как раз дочитываю "Чистый код" Роберта Мартина, и в разделе "Обработка ошибок" опять встретил этот настоятельный совет. Мотивация — использование исключений делает код более чистым и понятным. С такой формулировкой трудно поспорить, но жаль, что авторы таких советов никак не поясняют в своих книгах, в каких случаях использовать исключения, а в каких лучше не использовать.

Я встречал две крайности: разработчики, которые используют исключения везде, и разработчики, которые вообще не используют исключений. В первом случае объяснением было "потому что это круто правильно и объектно-ориентированно", в другом — "потому что они дают слишком большой оверхэд". И я задумался, кто из них прав? И, вообще, какова цена использования исключений в C++? Можно ли как-то управлять этим? Может, стоит выработать для себя какие-то правила?..

9 ноября 2010 г.

g++ 4.5 и clang

В Ubuntu 10.10 уже входит gcc 4.5, и я вчера решил собрать clang из репозитория. Всё было хорошо, пока процесс линковки не сожрал полтора гигабайта памяти. После этого он был торжественно убит системой, потому что у меня для виртуалки выделено всего полтора гигабайта. Попробовал собрать с gcc 4.4 — собрался без проблем.

Жаль, но gcc 4.5 всё-таки еще сыроват.

UPD: Смог добиться того, чтобы gcc 4.4 тоже сожрал больше 1,5 Гб. Для этого нужно включить дебаг-режим, включить ассерты и expensive checks, и выключить оптимизатор. Но это, конечно, извращение.

Еще жаль, что clang нельзя собрать без сборки llvm. Или я чего-то не знаю?