fk0, легенда (27.10.2017 08:20, просмотров: 1041) ответил IBAH на а пользует ли кто нибудь статические анализаторы кода? какие? где? когда? и какие кнопки нажимать? а то настойчивая реклама PVS-Studio заставляет задуматься...
Из доступных средств и хороших, на мой взгляд, следующие: 1) Статический анализатор встроенный в Vistual Studio и, в частности, в микрософт компилятор из неё. Компилятор может быть "условно бесплатно" добыт из недр Widnows SDK и/или Windows DDK -- скачан с сайта микрософта, в нём опция /analyze будет работать (но в самой студии оно доступно только в версии TeamEdition, которую хер кто тебе купит, впрочем запускать можно и без студии). Но это решение сложно интегрировать в свою билд-систему как правило. Хорошо обнаруживает некоторые, в основном связанные с вычислениями проблемы, некоторые не обнаруживает.
2) clang code analyzer -- он запускается через программу scan-build, которая условно говоря, следит за make, как он запускает gcc, и так же запускает свой анализатор. Т.е. возможна интеграция со сложной билд-системой. Способен обнаруживать очень сложные случаи для человека, например баг происходящий если вот эти 50 шагов произойдут с такими-то аргументами. Но при этом пропускает очевидные проблемы иногда. Более ориентирован на современный C++, нежели микрософт. Плохо обнаруживает утечки (хуже cppcheck иногда).
3) cppcheck -- плохой анализатор, он вообще не анализатор, он код до конца не разбирает, это просто набор правил применяемых к коду. Находит утечки памяти, не обнаруживаемые clang. Но чаще бесполезен, а то и вреден (много ложных срабатываний или ошибок).
4) Как ни странно GCC, современной версии (6.x или даже 7.x) и сборка программы под PC даёт массу нужных варнингов в нужных местах, если их конечно включить (помимо -Wall добавить массу нужных).
Динамический анализ, в рантайме, не так уж бесполезен и появляет выявить часть проблем труднообнаружимых в статике. Обычно имеет смысл только на x86, но иногда и на таргет-платформе.
Особенно хочется подчеркнуть, что нужно не бояться использовать malloc, а наоборот, использовать лишний раз, где можно и целесообразно. Это сильно облегчает отладку, потому, что отслеживать попадания за пределы массивов в статической памяти редко кто вообще умеет, сложно это.
Для запуска на x86 как правило архитектура ПО строится таким образом, что:
* реализуется слой абстракции отделяющий платформо-зависимый код от остального (HAL);
* реализуется "эмулятор" на x86 -- реализация HAL для ПК, которая ничего толком не делает, но симулирует поведение HAL на реальном железе (я такой HAL переложил на TCL-скрипты, благодаря чему было можно быстренько закодировать новое поведение HAL, без того чтобы связываться с отладкой C/C++ и здесь, благо скорость x86 всё позволяет, кроме того скрипты позволяют также быстро сделать какой-то GUI в котором в кнопки мышой тыкать можно, ну а сами скрипты могут симулировать сложные/длинные последовательности действий, что руками трудно сделать);
* для отладки самого HAL на реальном железе делаются тесты HAL отдельно от основной программы;
* разделение производится по тому принципу, чтоб максимум кода и, самое главное, управляющей логики вынести за HAL. Но при этом функции не дробятся слишком мелко, чтоб HAL всё же можно было реализовать на всех возможных платформах. Т.е. разделение не на уровне отдельных выводов контроллера всё же, а на уровне функциональных блоков (управление таким-то блоком аппаратуры);
* программа компилируется на x86 с HAL-эмулятором и отлаживается...
Какие средства отладки могут иметь смысл:
1) valgrind (для windows -- DrMemory), сам valgrind имеет несколько разных tools, интересны в основном memcheck (правильное обращение с динамически выделенной памятью), иногда callgrind, drd и massif;
2) использование современного gcc и включение опции "Address Sanitizer" (помимо динамической памяти отслеживает и статические массивы, чем хорош) и "Undefined Behavior Sanitizer" (отлавливает поведение, которое может отличаться на других платформах, что полезно для embedded);
3) gcc с опциями -fprofile-arcs и -ftest-coverage (это применимо, при желании, и на target-платформе) может понять code coverage, в основном полезно для тестов;
4) gcc с опцией -pg позволяет построить "профиль", говорящий о частоте вызовов и/или времени работы функций (но шаг времени большой обычно, мелкие функции тяжело измерить, только если в цикле запускать). Применимо так же и на target-платформе. Более того, возможны нетрадиционные использования данной функции: коллега умудряется через неё отслеживать положение стека в каждом потоке и может в любой момент времени для всех потоков дать backtrace и сказать чем они занимаются. Трюк только в том, что gcc с этой опцией для каждой функции, в её начале, вызывает некую твою функцию, где ты сохраняешь указатель стека. Очень полезно для отладки, если других способов уже нет.
5) gcc с опцией -finstrument-functions -- вызывает твою функцию на входе-выходе из всех функций, позволяет построить трассу программы или точно измерить время выполнения функций;
6) программы вроде Very Sleepy(для Windows), valgrind с инструментом callgrind, sysprof и т.п. средства -- для профилирования программы без перекомпиляции;
7) gcc с опцией "stack protector" -- полезен и на таргет-платформе, позволяет ловить случаи порчи стека (из-за buffers overflow и т.п.);
8) D.U.M.A. -- может быть перенацелена на таргет-платформу (если она на линуксе, а памяти не хватает, чтоб запускать там valgrind);
9) много ещё всяких ньюансов, сходу сложно всё назвать.
[ZX]