Миф о доказательном программировании без ошибок


Много копий сломано в обсуждениях, какой язык программирования самый лучший с точки зрения корректности и безопасности (под термином "корректность и безопасность" имеется ввиду отсутствие различных ошибок в программе, которые проявляют себя на стадии её выполнения и приводят к выдаче некорректного результата или неожиданному поведения). А некоторые языки программирования, такие как SPARK или OCaml, даже специально разрабатывались для облегчения доказательства корректности программы.


А возможно ли вообще писать программы без ошибок?


Корректность исходного кода != корректное выполнение программы


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


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


При этом, даже имея множественное резервирование ЭВМ, которые объединены с помощью высоконадежного мажоритарного элемента, у нас не будет 100% гарантии корректного выполнения экземпляра программы в силу различных внешних обстоятельств. Ведь они никак не зависят от кода (выход из строя вентилей микросхем ЭВМ, изменение состояние оперативной памяти из-за высокоэнергетической частицы космического излучения или искры статического напряжения при уборке серверной бабы Нюрой).


В свою очередь это означает, что даже при наличии строгого математического доказательства корректности программы, после ее трансляции в машинный код, все равно нет 100% гарантии в выполнении конкретного экземпляра приложения без сбоев и ошибок. Надежность, а следовательно и вероятность сбоя приложения из-за аппаратной составляющей, можно многократно повысить, но она все равно никогда не будет абсолютной.


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


Доказательное программирование не нужно?


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


Еще одним следствием невозможности доказательной корректности результата выполнения экземпляра приложения является необходимость реализации в любом языке программирования, который хочет претендовать на корректность и безопасную разработку будет наличие инструментов для обработки различных ошибочных ситуации в произвольные моменты времени (т.е. прерываний/исключений). И это касается даже самых надежных и "безопасных" языков, так как некорректное поведение экземпляра приложения возможно в любом участке исполняемой программы, даже там, где возникновения ошибочных ситуаций не ожидается.


К счастью, безопасность использования того или иного языка программирования важна не просто сама по себе как абсолютная величина. Она нужна как величина относительная для сравнения языков программирования между собой. И если достичь строгой доказательной безопасности отдельно взятого языка программирования невозможно, то сравнивать их между собой очень даже получится.


Правда при подобном сравнении нужно обязательно учитывать не только безопасность, которую декларирует новый язык, но и все остальные его свойства и характеристики. Чтобы не получилось так, что для использования нового языка программирования, нужно выбросить весь старый код и переписать все программы по новой.

@rsashka
28.02.2025 18:07 UTC
Первоисточник

Комментарии

@funca
28.02.2025 13:53 UTC
+1

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

@NickDoom
28.02.2025 15:37 UTC
+3

99% проблем из-за того, что абсолютно корректно написанная программа на абсолютно безопасном языке совершенно верно исполняет неправильное ТЗ. Они же — «неверная модель объекта управления» (для промышленного ПО это называется так, но во всех сферах есть аналоги).

@rsashka
28.02.2025 15:45 UTC
+1

"Без внятного ТЗ - результат ХЗ" :-)

28.02.2025 15:59 UTC
+2

Ну да, причём в момент перехода от человеческого языка к математической модели и возникает 99% хтони %) а на словах оно обычно тааак чётко выглядит… %)

28.02.2025 16:24 UTC
+1

Есть порочная практика, делаем внятный ТЗ делаем модель. => Пишем код.=> Корректируем ТЗ (хз почему) => модель неверна => результат кал. Заебца!

28.02.2025 19:46 UTC
+3

Ну как «почему» — в 90% случаев настоящее ТЗ выясняется уже только по ходу работы, и дело даже не в тех, кто это ТЗ ставит, а в том, что истинные свойства объекта управления обычно выясняются не на первом году такового управления %)

@Spyman
01.03.2025 18:42 UTC
+3

Мне всегда казалось что доказательное программирование - это не про этап выполнения а про результат компиляции. Что мы можем доказать, что на процессоре, как машине тьюринга, скомпилированный код приведёт к корректному ответу на корректных входных данных.

А это все уже доказывается на уровне математики - программа превращается в конечный автомат и доказывается соотвествие входных состояний выходным. (Ну это как я себе это вижу, скорее всего эксперты опишут это намного адекватнее)

А ошибки на уровне физики процессора или уж крайне маловероятное попадание космических лучей - это не про программирование вообще, а про риск менеджмент - в конце концов на ваш компьютер кирпич может упасть, но причём тут программирование?

@rsashka
01.03.2025 18:49 UTC
0

но причём тут программирование?

Так программирование нужно не само по себе. Нужен корректный результат выполнения программы. Естественно, что если программа написана неправильно, то и результат её выполнения будет неправильным.

Однако обратное утверждение неверно (что у правильной программы будет корректный результат выполнения), т.е. корректность самой программы (отсутствие в ней ошибок), это обязательное, но не достаточное условие получение правильного результата её выполнения.

02.03.2025 07:12 UTC
+1

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

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

Короче говоря зачем вы нам рассказываете о том что там у них негров линчуют когда у вас спрашивают конкретно про вашу ответственность в вашей зоне ответственности - корректность вашего кода. Вот когда вы докажите, что он у вас корректен вот тогда у вас и появиться право переводить стрелки на других, а пока это не произошло то ...

В общем за свою жизнь я ещё не разу не видел и даже не слышал про существование хотя бы одной корректной программы даже с большим списком оговорок.

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

03.03.2025 09:32 UTC
+1

Тут надо определиться мы про доказательное программирование говорим или про рациональность его применения.

Для меня статья выглядит как осуждение автомобиля, за то что в городе нет дорог.

Если в твоём городе нет дорог - очевидно что автомобиль тебе не подходит, но это не "миф об автомобиле" - как в заголовке статьи)

Если для конкретной задачи ошибка из за попадания космических лучей или сбоя физики процессора критична, это не значит что доказательное программирование плохо или не работает)

@dan4ik316
03.03.2025 15:47 UTC
+1

Если математически доказанная корректность программы не гарантирует защиту от непредвиденных аппаратных сбоев, то следует ли вкладывать ресурсы в формальные методы доказательной безопасности языка или же сосредоточиться на механизмах резервирования и устойчивости, и как найти оптимальный баланс между этими подходами?

@rsashka
03.03.2025 16:03 UTC
0

Формальные методы доказательства безусловно нужны. Иначе если на входе ерунда, то на выходе тоже будет ерунда при любой аппаратной платформе и проблема действительно именно в балансе.

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