Какие уровни должны анализировать статические анализаторы? - PullRequest
2 голосов
/ 04 марта 2011

Я заметил, что некоторые статические анализаторы работают с исходным кодом, в то время как другие работают с байт-кодом (например, FindBugs).Я уверен, что есть даже некоторые, которые работают с объектным кодом.

Мой вопрос прост: каковы преимущества и недостатки написания различных видов статических анализаторов для разных уровней анализа?

Под «статическими анализаторами» я включаю линтеры, средства поиска ошибок и даже полноценные верификаторы.А по уровням анализа я бы включил исходный код, высокоуровневые IR, низкоуровневые IR, байт-код, объектный код и плагины компилятора, которые имеют доступ ко всем фазам.

Ответы [ 2 ]

5 голосов
/ 05 марта 2011

Эти различные аспекты могут влиять на уровень, на котором анализатор может решить работать:

  1. Разработка статического анализатора - это лот работы. Было бы стыдно не учитывать эту работу для нескольких языков , скомпилированных с одним и тем же байт-кодом, особенно если байт-код сохраняет большую часть структуры исходной программы: Java (FindBugs), .NET (связаны различные инструменты Кодекс контрактов). В некоторых случаях общий целевой язык был составлен с целью анализа, хотя схема компиляции не следовала этому пути.

  2. Относительно 1, вы можете надеяться, что ваш статический анализатор будет немного дешевле в написании, если он работает на нормализованной версии программы с минимальным количеством конструкций. При разработке статических анализаторов необходимость писать обработку для repeat until, когда вы уже написали while do, является проблемой. Вы можете структурировать свой анализатор так, чтобы несколько функций были общими для этих двух случаев, но беззаботный способ справиться с этим - перевести одну на другую или перевести исходный код на промежуточный язык, который имеет только одну из них.

  3. С другой стороны, как уже указывалось в ответе Флэша Шеридана, исходный код содержит большую часть информации . Например, в языках с нечеткой семантикой ошибки на уровне исходного кода могут быть удалены путем компиляции. C и C ++ имеют множество «неопределенных поведений», когда компилятору разрешено делать все что угодно, включая генерацию программы, которая работает случайно. Хорошо, вы можете подумать, если ошибка не в исполняемом файле, это не проблемная ошибка. Но когда вы когда-нибудь перекомпилируете программу для другой архитектуры или со следующей версией компилятора, ошибка может появиться снова. Это одна из причин не выполнять анализ после любой фазы, которая потенциально может удалить ошибки.

  4. Некоторые свойства могут быть проверены только с достаточной точностью в скомпилированном коде . Это включает в себя отсутствие ошибок, представленных компилятором, на что снова указал Flash Sheridan, а также время выполнения в худшем случае . Точно так же многие языки не позволяют точно знать, что делает код с плавающей запятой, если только вы не посмотрите на сборку, сгенерированную компилятором (это потому, что существующее оборудование не позволяет им гарантировать больше). Тогда выбор состоит в том, чтобы написать неточный анализатор исходного уровня, который учитывает все возможности, или проанализировать точно одну конкретную компиляцию программы с плавающей запятой, если будет понятно, что именно этот код сборки будет выполняться .

1 голос
/ 04 марта 2011

Анализ исходного кода, как правило, наиболее полезен; иногда эвристика даже должна анализировать комментарии или форматирование. Но вы правы в том, что даже анализ объектного кода может быть необходим, например, для обнаружения ошибок, вызванных ошибками GCC . Томас Репс, глава GrammaTech и профессор из Висконсина, выступил с хорошей речью об этом в Стэнфорде пару лет назад: http://pages.cs.wisc.edu/~reps/#TOPLAS-WYSINWYX.

...