Libcwd
![]() | В этой статье есть несколько проблем. Пожалуйста, помогите улучшить его или обсудите эти проблемы на странице обсуждения . ( Узнайте, как и когда удалять эти шаблонные сообщения )
|
Libcwd — это библиотека C++, написанная Карло Вудом для добавления во время выполнения отладки поддержки приложений C++ , особенно кода, разработанного с помощью коллекции компиляторов GNU . Функциональность, которую библиотека добавляет в приложение, можно разделить на три категории:
- Ostream . Отладочный вывод на основе
- Доступ во время выполнения к отладочной информации.
- Доступ во время выполнения к администрированию распределения памяти .
Поддерживаемые платформы
[ редактировать ]Хотя сам код библиотеки пытается быть строго ISO C++ и соответствовать POSIX максимально , для достижения пунктов 2 и 3 необходим довольно специализированный код, специфичный для архитектуры, на которой работает приложение. По этой причине Libcwd ограничивает себя узкой архитектурой: он должен быть скомпилирован с помощью компилятора GNU и требует, чтобы объектный код был 32- или 64-битным ELF , а компилятор генерировал отладочную информацию в формате DWARF-2 .
В результате компиляции libcwd создаются две библиотеки: потокобезопасная ( libcwd_r) и версия (libcwd) без поддержки потоков. Потокобезопасная версия зависит от еще большего количества деталей, специфичных для архитектуры (а именно, от библиотеки GNU C). В результате полнофункциональная библиотека libcwd в основном подходит только для разработки на платформах Linux .
Однако libcwd можно настроить так, чтобы отказаться от поддержки потоков, отладки распределения памяти и/или чтения отладочной информации ELF и DWARF-2 — до тех пор, пока не останется только поддержка вывода отладки ostream. Таким образом, можно использовать его для разработки приложения на Linux до тех пор, пока оно не станет надежным, и при этом иметь отладочные данные на других (POSIX) платформах, даже если полноценная библиотека libcwd там недоступна — при условии, что потокобезопасность не требуется. для вывода отладки на этих платформах: два или более потоков, записывающих вывод отладки в один и тот же поток, могут привести к довольно беспорядочному выводу, когда вывод одной строки начинается в середине другой без поддержки потоков.
Отладочный вывод на основе Ostream
[ редактировать ]Libcwd предоставляет несколько макросов, которые легко расширяются, позволяя пользователю делать практически все, что он обычно может делать с потоками ostreams. Однако, если вы просто хотите записать отладочный вывод, двух макросов будет достаточно: Dout и DoutFatal. Последний должен использоваться для фатального вывода отладки, после чего приложение необходимо закрыть. Например:
if (error)
DoutFatal(dc::fatal, "An unrecoverable error occurred.");
Разница с Dout заключается в том, что когда приложение компилируется без кода отладки, макрос Dout() заменяется ничем, а DoutFatal() заменяется кодом, который печатает выходные данные и завершает работу (способом, который может определить пользователь).
Простой вывод отладки записывается с помощью Dout следующим образом:
Dout(dc::notice, "called from " << location_ct(CALL_ADDR));
где второй параметр может содержать '<<' для записи любого типа или объекта в выходной поток отладки (в данном случае location_ct).
«dc::fatal» и «dc::notice» — это «каналы» отладки, которые можно включать и выключать. Пользователь может создавать и использовать любое количество пользовательских каналов отладки, помимо стандартных . Также возможно создать больше, чем просто объект ostream вывода отладки по умолчанию «libcw_do», и, таким образом, записать вывод в более чем один ostream. Каждый объект отладки, представляющий ostream, в свою очередь, может быть отдельно включен и выключен.
Доступ во время выполнения к отладочной информации
[ редактировать ]Эта информация включает в себя возможность поиска исходного файла и номеров строк, а также имен функций. В результате можно, например, написать вывод отладки, в котором будет указано, кто вызвал данную функцию, или имя текущей функции, даже если эта функция является сложным шаблоном. Например,
PERSIST : PersistXML::serialize_builtin<std::string>("M_hostname", @0xbfc1f214) is called.
Доступ во время выполнения к администрированию распределения памяти
[ редактировать ]Libcwd осуществляет внутреннее управление распределением памяти. Это позволяет выполнять такие действия, как проверка утечек памяти , распечатка обзора выделенной памяти (очень мощным способом, позволяющим фильтровать что угодно: регулярные выражения для имен библиотек, имен функций (разобранных или нет) и/или времени. интервалы, в течение которых производились распределения).
Библиотека также предоставляет несколько глобальных функций, которые можно вызывать из отладчика, например gdb , что позволяет разработчику быстро узнать, на какое выделение указывает данный указатель. Например,
(gdb) call cwdebug_alloc(0x8a19450) 0x8a19450 points inside a memory allocation that starts at 0x8a19448 start: 0x8a19448 size: 12 type: char** description: Array of commandline arguments passed to libcw_app_ct::options_done_event. location: libcw_app.cc:304 in function: libcw_app_ct::libcw_init(int, char* const*) when: 00:31:09.888760 (gdb) l libcw_app.cc:304