Показаны сообщения с ярлыком clang. Показать все сообщения
Показаны сообщения с ярлыком clang. Показать все сообщения

вторник, 6 октября 2009 г.

Статический анализ кода

 Недавно, в моем проекте возникла проблема. Суть ее заключалась в не стабильных крэшах приложения, которые было очень трудно воспроизвести и редко повторялись, но тем не менее они присутстовали, чем сильно раздражали. Главая из версий, объясняющая их была до банальности проста – не коректная работа с памятью. На поиски освобожденных / не освобожденных объектов было потрачено не один день. Было найдено и справленно несколько других багов связанных с памятью, но это не привело к ожидаемому результату.
 Буквально недавно, я узнал, что в Xcode 3.2 есть возможность статического анализа кода. Статический анализ – это анализ выполняемый над версией кода, с целью выявления мест содержащих ошибки. Встроеный в Xcode 3.2 анализатор, основан на консольном анализаторе clang. Если вы щасливый обладатель OS X Snow Leopard и Xcode 3.2, то советую вам прочитать статью из эпловской документации:
иначе читаем далее.

Для начала нам предстоит установить анализтор clang. Для этого мы должны скачать архив checker-0.223.tar.bz2 с сайта:




и распаковать его, скажем, на рабочий стол. В итоге, на вашем рабочем столе, у вас окажется папка checker-0.223. Теперь переместим папку checker-0.223 в дирректорию /usr/bin. Запустите Терминал, перейдите на Рабочий стол и выполните команду:

sudo mv checker-0.223 /usr/bin/

Теперь перейдите в папку /usr/bin/ и создайте символьные ссылки на статический анализатор и просмотрщик результатов:

sudo ln -s checker-0.223/scan-build scan-build
sudo ln -s checker-0.223/scan-view scan-view

На этом установка анализатора завершена. Перейдем непосредственно к настройке проэкта. Настраивать особо много не прийдется, только Code sign и Base SDK. Для настройки Code sign, зайдите в настройки таргета, на вкладку Build, перейдите в секцию Code signing и для ключа Any iPhone Device выберете Don't Code Sign:





Теперь зайдите в настройки проэкта, на вкладку General и выберите iPhone Simulator 2.1 для Base SDK for All Configurations.



На этом настройка проекта окончена, можно преступать непосредственно к билду и анализу, кода.

При установке Xcod'а, по умолчанию установливается замечательная консольная утилита xcodebuild. Она позволяет собирать ваш проект из под консоли. Именно связка xcodebuild + scan-build, даст нам возможность найти баги в нашем коде.

Создадим новый Window Based проект с названием TestProject и добавим в метод applicationDidFinishLaunching код:

NSString *testString;
NSString *testString2;
testString2 = [testString copy];


Сразу предупрежу вас, что код заведомо содержит ошибки. Они созданы с целью показать возможности статического анализатора.

Теперь сохраним проект, запустим консоль и перейдем в папку проекта. Остается только выполнить статический анализ. Очень хорошо, перед каждым анализом очистить проект. Для этого вызовете команду:


scan-build xcodebuild -configuration Debug clean

ну и после ее выполнения, запустите сам статический анализатор:

scan-build -k -V xcodebuild -configuration Debug

В результате, после билда и анализа у вас в консоль напишется что то типа того:





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

cd /var/folders/qE/qEWzPoglGVWOVJJ2d-amzU+++TI/-Tmp-/scan-build-2009-10-05-1
open index.html

В результате у вас загрузится браузер, в котором будет html отчет отображающий результат анализа:




Сам отчет разделен на 3 части:
  1. информация о билде (пользователь, дата путь);
  2. количество найденных багов, разбитые на категории;
  3. список файлов, в которых найдены баги.
Для удобства вы можете выбрать определенный тип ошибок, убрав или проставив галочки. Наибольший же интерес для нас представляет раздел Reports, в котором, как сказанно выше, отображается список файлов в которых найдены баги. Нажав на ссылку View Report, вы можете просмотреть подробный отчет по определенной ошибке в файле. В подробном отчете отображается линия в которой найдено уязвимое место и примерное описание что не так. Вам остается хорошенько проанализировать код, ведь анализатор не искуственный интеллект, и если уязвимость подтверждается, исправить ее.

Если честно, для меня остается загадкой, по какому приницпу определяются файлы в которых присутствуют ошибки. Так как бывали такие места, в которых явно были “опсные” места, а анализатор не помечал их. Надеюсь в ближайшем будущем я разберусь в этом и подправлю статью. Хоть анализатор нашел в проекте несколько критических утечек, но все равно приходится быть внимательным. Чего и вам желаю.




четверг, 3 сентября 2009 г.

iPhone static library

Библиотеки были придуманы для объединения схожей функциональности в отдельные модули, которые могли использоваться совместно несколькими разработчиками.

В мире *nix систем да и вообще в мире OC существует 2 вида библиотек.

  1. динамические;
  2. статические.

Каждый тип библиотек имеет свои достоинства и не достатки. Прозрачный механизм создания динамических библиотек под iPhone отсутствует, хотя лично мое мнение – я не вижу большого смысла в использовании их под iPhon'ом. Нам же, наибольший интерес, представляют статические библиотеки, речь о которых пойдет далее в статье.

Статическая библиотека – это хороший способ повтороного использования кода. Кроме того, в некоторых проектах, при использовании множества не маленьких OpenSource – решений применение статических библиотек – отличный вариант сократить время на перекомпиляцию проекта. Это достигается путем хранения заранее обработанного компилятором исходного кода в объектные файлы.

В nix системах, как правило, статические библиотеки имеют расширение *.a. Таким образом, статическая библиотека – это архив, содержащий в себе объектные файлы.

То что это архив, а не, скажем, цельный бинарник, вы можете убедиться путем разархивации его. Для этого вам необходимо в терминале выполнить комнаду:

ar -xимя_статической_библиотеки

В результатет, в том же каталоге, у вас должны появиться распакованные объектные файлы.

Итак, перейдем к практике. Практиковаться мы будем, на свежесозданном проекте и исходниках обертки над sqlite – FMDatabase.

  1. Для этого создадим новый проект, к примеру Window-based Application, (тип проекта может быть любой) и назовем его MakeStaticLib. Далее, для удобства, создадим новую группу для обертки, привяжем ее к папке и добавим в нее исходники.
  2. Нажмем правой кнопкой, на группу Classes и выберем пункт AddNew group. Свежесозданную группу назовем FMDatabase и создадим для нее одноименную папку. Для этого зайдем в свойства группы FMDatabase, нажмем на кнопку Choose и выберем папку, где мы хотим хранить исходники.
  3. Добавим исходники FMDatabase в проект, (взять их можно с сайта http://code.google.com/p/flycode/)
  4. На этом подготовительная часть окончена, теперь приступим непосредственно к созданию библиотеки. Для этого нажмем правой кнопокй на раздел Targets и выберем пункт AddNew Target.
  5. В появившемся окне выберем тип target'а Static Library, назовем ее FMDatabase и нажмем Finish. В результате структура проекта должна получиться следующая:
  6. Теперь приступим непосредственно к добавлению исходников к статической библиотеки. Здесь прячется небольшая хитрость. Дело в том, что при добавлении исходников в проект, по умолчанию они добавляются в главный таргет, а он у нас является MakeStaticLib. На простороах сети, в основном, я встречал способ, при котром файлы добавлялись напрямую в Static lib target, но к сожалению с первого раза я не смог повторить этот трюк и нашел другой, на мой взгляд, более красивый способ. Для этого выберем ТОЛЬКО *.m файлы, которые мы хотим, чтоб присутствовали в библиотеке, выбрем у них пункт Get Info, перейдем на вкладку Targets и сменим “пункт назначения” c MakeStaticLib на FMDatabase:
  7. Далее добавим библиотеку в наш проект. Для этого мы зайдем в свойства таргета MakeStaticLib на вкладку General, и выберем один из 2х способов. Первый способ заключается в том, что мы добавим библиотеку как Direct dependencies объект. Это дает возможность, после изменения кода библиотеки, автоматически перекомпилировать статическую библиотеку во перекомпиляции всего проекта. Иначе, если вы вебрете второй способ, добавления библиотеки как Linked Libriries объект, вам будет необходим сперва перекомпилировать библиотеку вручную, а потом сам проект. На мой взгял это не совсем удобно и я бы вам порекомендовал добавлять как Direct dependencies объект.
  8. И наконец последний пункт, который многие не понимают зачем делать, так как и без него все работает. Для того, чтобы в библиотеки нормально отрабатывали возможности языка Objective C (к примеру категории) необходимо добаить флаг -ObjC к флгам линковщика (Other linker flags). Делается это в Info таргета MakeStaticLib, на вкладке Build в секции Linking.

На этом создание статической библиотеки окончено.