Введение

Подход к статическому анализу программ
В информатике абстрактная интерпретация – это теория обоснованного приближения семантики компьютерных программ, основанная на монотонных функциях над упорядоченными множествами, в частности решетками. Её можно рассматривать как частичное выполнение компьютерной программы, позволяющее получить информацию о её семантике (например, о потоке управления и потоке данных) без выполнения всех вычислений. Основным практическим применением является формальный статический анализ – автоматическое извлечение информации о возможных выполнениях компьютерных программ. Такие анализы имеют два основных применения:
внутри компиляторов для анализа программ с целью определения применимости определенных оптимизаций или преобразований;
для отладки или даже сертификации программ на предмет отсутствия определенных классов ошибок. Абстрактная интерпретация была формализована французскими учеными-компьютерщиками Патриком Кузо и Радией Кузо в конце 1970-х годов.

Интуиция

В этом разделе иллюстрируется абстрактная интерпретация с помощью реальных, невычислительных примеров. Рассмотрим людей в конференц-зале. Предположим, что у каждого человека в комнате есть уникальный идентификатор, например, номер социального страхования в США. Чтобы доказать отсутствие кого-либо, достаточно проверить, отсутствует ли его номер социального страхования в списке. Поскольку два разных человека не могут иметь один и тот же номер, можно доказать или опровергнуть присутствие участника, просто проверив его номер. Однако возможно, что были зарегистрированы только имена присутствующих. Если имя человека не найдено в списке, мы можем безопасно заключить, что этого человека не было; но если имя найдено, мы не можем сделать однозначный вывод без дальнейших уточнений из-за возможности омонимии (например, два человека по имени Джон Смит). Обратите внимание, что эта неточная информация все равно будет достаточной для большинства целей, поскольку омонимы встречаются редко на практике. Однако, при всей строгости, мы не можем с уверенностью утверждать, что кто-то присутствовал в комнате; мы можем лишь сказать, что он, возможно, был здесь. Если человек, которого мы ищем, является преступником, мы поднимем тревогу, но, конечно, существует вероятность ложной тревоги. Аналогичные явления будут возникать при анализе программ. Если нас интересует только определенная информация, например, "был ли в комнате человек определенного возраста?", то нет необходимости вести список всех имен и дат рождения. Мы можем безопасно и без потери точности ограничиться списком возрастов участников. Если это окажется слишком сложно, мы можем хранить только возраст самого молодого и самого старого человека. Если вопрос касается возраста, строго меньшего или строго большего определенного значения, то мы можем безопасно ответить, что такого участника не было. В противном случае мы можем лишь сказать, что нам неизвестно. В области вычислений конкретная и точная информация, как правило, не может быть вычислена за конечное время и с использованием конечной памяти (см. теорему Райса и проблему останова). Абстракция используется для получения обобщенных ответов на вопросы (например, ответа "возможно" на вопрос "да/нет", что означает "да или нет", когда мы – алгоритм абстрактной интерпретации – не можем вычислить точный ответ с уверенностью); это упрощает задачи, делая их доступными для автоматического решения. Важным требованием является добавление достаточной неопределенности, чтобы сделать задачи управляемыми, сохраняя при этом достаточную точность для ответа на важные вопросы (например, "может ли программа аварийно завершить работу?").

Абстрактная интерпретация компьютерных программ

При наличии языка программирования или спецификации, абстрактная интерпретация состоит в определении нескольких семантик, связанных отношениями абстракции. Семантика – это математическая характеристика возможного поведения программы. Наиболее точная семантика, очень близко описывающая фактическое выполнение программы, называется конкретной семантикой. Например, конкретная семантика императивного языка программирования может сопоставлять каждой программе множество возможных трасс выполнения – трасса выполнения является последовательностью возможных последовательных состояний выполнения программы; состояние обычно состоит из значения счётчика программы и расположений памяти (глобальные переменные, стек и куча). Затем выводятся более абстрактные семантики; например, можно рассматривать только множество достижимых состояний в трассах выполнения (что эквивалентно рассмотрению последних состояний в конечных трассах). Цель статического анализа – получить вычислимую семантическую интерпретацию в определённый момент. Например, можно выбрать представление состояния программы, работающей с целочисленными переменными, путём игнорирования фактических значений переменных и сохранения только их знаков (+, − или 0). Для некоторых элементарных операций, таких как умножение, такая абстракция не приводит к потере точности: для определения знака произведения достаточно знать знаки операндов. Для других операций абстракция может терять точность: например, невозможно определить знак суммы, операнды которой имеют соответственно положительный и отрицательный знаки. Иногда потеря точности необходима для обеспечения разрешимости семантики (см. теорему Райса и проблему останова). В общем случае, необходимо искать компромисс между точностью анализа и его разрешимостью (вычислимостью) или практической применимостью (вычислительной сложностью). На практике определяемые абстракции адаптируются как к свойствам программы, которые требуется анализировать, так и к набору целевых программ. Первый крупномасштабный автоматизированный анализ компьютерных программ с использованием абстрактной интерпретации был вызван аварией, приведшей к разрушению первого полёта ракеты Ariane 5 в 1996 году.