Теоретично програми без помилок


12

Я прочитав багато статей, в яких зазначається, що код не може бути помилковим, і вони говорять про ці теореми:

Насправді теорема Райса виглядає як імплікація проблеми зупинки, і проблема зупинки знаходиться в тісному взаємозв'язку з теоремою про незавершеність Геделя.

Чи означає це, що кожна програма матиме хоча б одну ненавмисну ​​поведінку? Або це означає, що неможливо написати код для його перевірки? Що щодо рекурсивної перевірки? Припустимо, що у мене дві програми. У них обох помилок, але вони не мають однакових помилок. Що буде, якщо я буду запускати їх одночасно?

І звичайно, більшість дискусій говорили про машини Тьюрінга. Що з лінійно-обмеженою автоматизацією (справжні комп'ютери)?


10
Я впевнений, що ця програма python робить все, що призначено робити, і не більше: print "Hello, World!"... чи можете ви бути трохи більш зрозумілими?
durron597

2
@ durron597: Чи існує ринок такого програмного забезпечення? Привіт, світові принтери, перезавантажена версія? Тепер з більшою кількістю привіт та більше світів?
JensG

1
@Phoshi faugh. Цілком можливо написати досить просту програму (скажімо, за допомогою дротів на макетній дошці), щоб ви могли побачити весь обсяг цього процесу відразу і без помилок. Ви нападаєте на деталі мого коментаря, не звертаючись до мого основного моменту, в тому, що можна писати надзвичайно прості програми, у яких немає помилок.
durron597

2
@Phoshi "Доведіть, що ваш інтерпретатор python не має помилок." Помилки в реалізації python не роблять програму помилковою. Програма є коректною, якщо вона робить те, що передбачається, враховуючи, що реалізація Python відповідає мовній специфікації. Будь-який доказ сприймає деякі речі як аксіоми - ви, наприклад, повинні будете припускати, що Всесвіт буде існувати протягом усього виконання програми. Якщо у CPython є помилка, результат може бути неправильним, але помилка не була в програмі.
Doval

11
Жодна з цих теорем не має нічого спільного з помилками або наявністю програм, що не містять помилок. Вони є теоремами про те, на які питання відповідають обчислення. Ці теореми показують, що є деякі проблеми, які неможливо обчислити, і деякі математичні пропозиції, які не можна ні довести, ні спростувати, але вони, безумовно, не говорять про те, що у всіх програмах є помилки або що конкретні програми не можуть бути доведені правильними.
Чарльз Е. Грант

Відповіді:


18

Це не так багато програм, які не можуть бути помилками; це дуже важко довести, що вони є, якщо програма, яку ти намагаєшся довести, нетривіальна.

Зауважте, не через відсутність спроб. Типові системи повинні забезпечувати певну впевненість; Haskell має дуже складну систему типу, яка робить це в певній мірі. Але ніколи не можна усунути всю невизначеність.

Розглянемо наступну функцію:

int add(int a, int b) { return a + b; }

Що може піти не так у цій функції? Я вже знаю, що ти думаєш. Скажімо, ми покрили всі основи, як-от перевірка на переповнення тощо. Що станеться, якщо космічний промінь вразить процесор, змусивши його виконати

LaunchMissiles();

натомість?

Гаразд, можливо, це трохи надумано. Але навіть такі прості функції, як addфункція вище, повинні працювати в середовищах, де процесор постійно змінює контексти, перемикаючись між декількома потоками та ядрами. У такому середовищі може статися все, що завгодно. Якщо ви сумніваєтесь у цьому, то вважайте, що оперативна пам'ять є надійною не тому, що вона не містить помилок, а тому, що у неї є вбудована система для виправлення бітових помилок, які неминуче трапляються.

Я знаю, що ти думаєш. "Але я говорю про програмне забезпечення, а не про апаратне забезпечення".

Існує багато методик, які можуть підвищити рівень вашої впевненості в тому, що програмне забезпечення працює так, як належить. Функціональне програмування - одна з них. Функціональне програмування дозволяє краще обґрунтувати паралельність. Але функціональне програмування не є доказом, це більше, ніж одиничні тести.

Чому? Тому що у вас такі речі називаються крайовими справами.

І як тільки ви лише трохи перестанете простоту return a + b, довести правильність програми стає надзвичайно важко .

Подальше читання
вони пишуть правильні речі
Вибух Ariane 5


6
Розглянемо цілком правильну функцію типу: int add(int a, int b) { return a - b; }
Дональд стипендіатів

@DonalFellows: саме тому я включив посилання про Аріану 5.
Роберт Харві

2
@DonalFellows - Математична характеристика не вирішує проблему, вона лише переміщує її в інше місце. Як довести, що математична модель насправді представляє потребу клієнта?
mouviciel

1
@JohnGaughan Це передбачає взаємозалежності між модулями. З огляду на модулі, які виявились правильними та виявились незалежними один від одного, ви можете рекурсивно складати їх у більші модулі, які також, як відомо, є правильними та незалежними ad infinitum.
Doval

1
@JohnGaughan Якщо інтеграція модулів спричиняє помилки, то ви не змогли довести, що вони незалежні. Створення нових доказів із встановлених доказів не є більш важким, ніж побудова доказів з аксіом. Якби математика ставала експоненціально важче таким чином, математики були б накручені. Ви можете мати помилки у своїх сценаріях побудови, але це окрема програма. Немає жодного елемента таємниці, який би пішов не так, коли ви намагаєтеся складати речі, але залежно від кількості побічних ефектів довести, що спільного стану немає.
Doval

12

По-перше, давайте встановимо, в якому контексті ви хочете обговорити це. Програми програмування на питаннях Stack Exchange припускають, що вас, швидше за все, цікавить існування інструментів / мов у реальному світі, а не теоретичні результати та теореми інформатики .

Я прочитав безліч статей, у яких зазначено, що код не може бути помилковим

Сподіваюсь, що ні, тому що таке твердження є невірним. Хоча загальноприйнято вважати, що більшість масштабних додатків не є помилками, наскільки я знаю.

Найчастіше всього прийнято, що там дійсно НЕ існує (тобто існування, а не вибір) інструмент , який прекрасно визначити , є чи програма , написана на Тьюрингу мову програмування повністю помилка безкоштовно.

Недоказ - це інтуїтивне розширення проблеми зупинки, поєднане з даними спостереження щоденного досвіду.

Там же EXIST програмного забезпечення , яке може зробити «доказ правильності » , що переконатися , що програма відповідає відповідним формальним специфікації для програми.

Чи означає це, що кожна програма матиме хоча б одну ненавмисну ​​поведінку?

Ні. Хоча в більшості застосунків було виявлено щонайменше одну помилку чи ненавмисну ​​поведінку.

Або це означає, що неможливо написати код для його перевірки?

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

Для отримання більш детальної інформації див. Coq - це такий інструмент / мова / система.

Що щодо рекурсивної перевірки?

Не знаю. Я не знайомий з цим, і не впевнений, чи це проблема з обчислюваністю, чи проблема оптимізації компілятора.


1
+1 за те, що вперше заговорили про офіційні характеристики та помічники. Це важливий момент, якого бракує у попередніх відповідях.
Арсеній Муренко

6

Я хочу запитати, чи означає це, що кожен код матиме хоча б одну ненавмисну ​​поведінку?

Ні. Правильні програми можуть бути і написані. Зауважте, що програма може бути правильною, але її виконання може бути невдалим через, наприклад, фізичних обставин (як це написав користувач Роберт Харві у своїй відповіді тут ), але це явна річ: код програми все ще правильний. Якщо бути точнішим, збій викликаний не помилкою або помилкою в самій програмі, а в базовій машині, яка її виконує (*).

(*) Я запозичую визначення несправності , помилки та відмови з поля надійності, як, відповідно, статичний дефект, неправильний внутрішній стан та неправильне зовнішнє спостережуване поведінку відповідно до його специфікацій (див. <Будь-який папір із цього поля>) .

Або це означає, що я не в змозі написати код, який перевірятиме його?

Зверніться до загального випадку у викладі вище, і ви маєте рацію.

Можливо, ви зможете написати програму, яка перевіряє правильність конкретної програми X. Наприклад, якщо ви визначите програму "привіт світ" як одну з двома інструкціями послідовно, а саме, print("hello world")і exitви можете написати програму, яка перевіряє, чи є її вхід програмою, що складається з цих двох інструкцій послідовно, таким чином повідомляючи, чи це правильна програма "привіт світ" чи ні.

Те, що ви не можете зробити, використовуючи поточні рецептури, - це написати програму, щоб перевірити, чи якась довільна програма зупиняється, що передбачає неможливість тестування на правильність у загальних випадках.


4

Запуск двох або більше варіантів однієї програми - це відома методика відмовостійкості, яка називається програмою N-варіанту (або N-версії). Це підтвердження наявності помилок у програмному забезпеченні.

Зазвичай ці варіанти кодуються різними командами розробників, використовуючи різні компілятори, а іноді виконуються на різних процесорах з різними ОС. Результати голосуються, перш ніж надходити користувачеві. Boeing та Airbus люблять подібну архітектуру.

Залишаються дві слабкі ланки, що призводять до помилок у звичайному режимі:

  • Є лише одна специфікація.
  • система голосування є або унікальною, або складною.

5
Я вважаю, що НАСА чи інша космічна програма припустили, що N-варіант страждає від проблеми, що занадто часто програмісти думають однаково, і, таким чином, самостійно пишуть майже еквівалентні програми із загальними недоліками, коли недолік виходить за межі найтривіального рівня. Наприклад, посилайтеся на ту саму довідкову інформацію (див. Давню помилку у двійковому пошуку ), схильні використовувати ті самі алгоритми та допускати однакові помилки.
mctylr

@mctylr - Це дуже вдалий момент. Але насправді до недавнього часу в пам'яті не вистачало місця для зберігання більше одного варіанта програмного забезпечення на космічному кораблі. Їх відповідь - тест, тест, тест, промивання, повторення.
mouviciel

Програма космічного човника використовувала три незалежні конфігурації голосування системи. Будь-які голоси "проти" означали (або, справді, підказували), що система більше не є правильною, і її приймали в автономному режимі.

4

Програма має певні специфікації та працює в якомусь середовищі.

(приклад космічного проміння в інших відповідях змінюється addна те, що FireMissiles можна вважати частиною "середовища")

Якщо припустити, що ви можете формально вказати передбачувану поведінку програми (тобто її специфікацію) та її оточення, то іноді можна офіційно довести, що програма є в такому точному сенсі без помилок (тому її поведінка чи вихід поважає формалізацію її специфікації при формалізації її оточення).

Зокрема, ви можете використовувати аналізатори статичного джерела звуку, наприклад, Frama-C .

(але сучасний стан таких аналізаторів не дозволяє проаналізувати всю програму та підтвердити масштабні програми, такі як компілятор GCC або браузер Firefox або ядро ​​Linux; я вважаю , що подібні докази не відбудуться в моєму житті Я народився в 1959 році)

Однак, ви довели, що це правильна поведінка програми, якась певна специфікація в деяких (класах) середовищі.

Практично кажучи, ви можете (а NASA або ESA, мабуть, хоче) довести, що деякі програмні засоби космічних кораблів "не помилки" wrt деякі точні та формалізовані специфікації. Але це не означає, що ваша система завжди буде вести себе так, як ви хочете.

Простіше кажучи, якщо ваш робот космічного корабля зустрічається з якимось еталоном, і ви цього не вказали, немає жодного способу змусити вашого робота поводитись так, як ви насправді хочете ....

Читайте також записи в блозі Дж. Пітрата .

До речі, проблема зупинки чи теорема Геделя, ймовірно, стосується також людського мозку, або навіть людського виду.


Може бути, краще прикладу SEU зміна призову Addдо LaunchMissilesб ЙОМУ змін деяких значень даних , що в кінцевому підсумку призводить до помилкового виклику LaunchMissiles. СЕУ - проблема з комп’ютерами, які виходять у космос. Ось чому сучасні космічні апарати часто літають на декількох комп'ютерах. Це додає новий набір проблем, одночасність управління та надмірності управління.
Девід Хаммен

3

Чи означає це, що кожна програма матиме хоча б одну ненавмисну ​​поведінку?

Немає.

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

Теореми про незавершеність Геделя мають подібну до них сіру область. Враховуючи математичну систему достатньої складності, існуватимуть деякі твердження, зроблені в контексті тієї системи, правдивість якої неможливо оцінити. Це не означає, що математики повинні відмовлятися від ідеї доказування. Доказ залишається наріжним каменем математики.

Деякі програми можуть бути доведені правильними. Це непросто, але це можна зробити. У цьому полягає мета доведення формальної теореми (частина формальних методів). Теореми про незавершеність Геделя справді вражають: Не всі програми можуть бути доведені правильними. Це не означає, що використовувати формальні методи вкрай безрезультатно, оскільки деякі програми справді можуть бути офіційно доведеними як правильні.

Примітка. Формальні методи виключають можливість космічного проміння вражати процесор і виконувати launch_missiles()замість нього a+b. Вони аналізують програми в контексті абстрактної машини, а не реальних машин, що піддаються розладам подій, таких як космічний промінь Роберта Харві.


1

Тут є багато хороших відповідей, але всі вони здаються спідницями навколо критичної точки, яка полягає в тому, що всі ці теореми мають схожу структуру і говорять подібні речі, а те, що вони говорять, не "неможливо, ймовірно, написати правильно програми »(для деякого конкретного значення" правильно "і" програма " , яка варіюється в кожному окремому випадку), але то , що вони роблять слово" це неможливо запобігти кого - то писати невірну програму , яку ми не можемо бути неправильним "( тощо).

Беручи конкретний приклад проблеми зупинки, різниця стає яснішою: очевидно, що існують програми, які суттєво зупиняються, та інші програми, які ніколи не припиняються. Те, що існує третій клас програм, поведінку яких неможливо визначити жодним чином, не є проблемою, якщо все, що ми хочемо зробити, - це написати програму, що зупиняється на доказуванні, оскільки ми можемо просто уникати написання програми, що належить до цього класу.

Те саме стосується теореми Райса. Так, для будь-якого нетривіального властивості програми ми можемо написати програму, яка не може ні мати цю властивість ні доказовою, ні хибною; ми також можемо уникати написання такої програми, оскільки ми можемо визначити, чи програма є доказовою.


0

Моя відповідь буде з точки зору реального світового бізнесу та викликів, з якими стикається кожна команда розробників. Те, що я бачу в цьому питанні та багато відповідей, справді стосується контролю дефектів.

Код може бути помилковим. Візьміть будь-який з зразків коду "Hello World" для будь-якої мови програмування та запустіть те, що на платформі призначено, і воно буде працювати послідовно та давати бажані результати. Тут закінчується будь-яка теорія про неможливість відсутності помилок коду.

Потенційні помилки надходять у міру ускладнення логіки. Простий приклад Hello World не має логіки і щоразу робить те саме статичне. Як тільки ви додаєте логічну динамічну поведінку, це вводить складність, що призводить до помилок. Сама логіка може бути хибною, або дані, які вводяться в логіку, можуть змінюватися таким чином, як логіка не обробляє.

Сучасний додаток також залежить від бібліотек часу виконання, CLR, проміжного програмного забезпечення, баз даних тощо, які, заощаджуючи загальний час розробки, також є шарами, де помилки в цих шарах можуть існувати і залишатися непоміченими через тестування розробки та UAT та на виробництво.

Нарешті, ланцюжок додатків / систем, що додаток споживає дані, що живлять його логіку, - це всі джерела потенційних помилок або в межах їх логіки, або в межах програмного забезпечення, на якому логіка їде зверху, або вищестоящих систем, за якими вона споживає дані.

Розробники не мають 100% контролю над кожною рухомою частиною, підтримуючи логіку їх застосування. Власне, ми не дуже контролюємо. Ось чому тестування блоків є важливим, а конфігурація та управління змінами - важливі процеси, які ми не повинні ігнорувати або бути лінивими / неохайними.

Крім того, документовані угоди між вашою програмою, яка споживає дані з джерела, що не є вашим контролем, що визначає конкретний формат і характеристики для переданих даних, а також будь-які обмеження або обмеження, за які ваша система передбачає, що джерельна система несе відповідальність за те, щоб вихід був у межах ці межі.

У реальному застосуванні інженерії програмного забезпечення ви не зможете змусити його летіти, пояснивши бізнесу, чому теоретично програми не можуть бути помилками. Дискусії подібного характеру між технологією та бізнесом ніколи не відбудуться, за винятком наслідків технологічної несправності, яка вплинула на здатність бізнесу заробляти гроші, запобігати втраті грошей та / або підтримувати людей в живих. Відповідь "як це може статися" не може бути "дозвольте мені пояснити цю теорію, щоб ви зрозуміли".

З точки зору масових обчислень, які теоретично могли б зайняти назавжди, щоб виконати обчислення і отримати результат, додаток, яке не може закінчити і повернутися з результатом, - це помилка. Якщо характер обчислень такий, що це забирає багато часу та обчислює великі витрати, ви приймаєте цей запит і надаєте користувачеві зворотній зв'язок, як / коли вони зможуть отримати результат, і розпочинаєте паралельні нитки, щоб перетворити його. Якщо це має відбутися швидше, ніж це можна зробити на одному сервері, і бізнес є досить важливим, то ви можете масштабувати його на стільки систем, скільки потрібно. Ось чому хмара дуже приваблива, і можливість розкручувати вузли, щоб взяти на себе роботу і відкрутити їх вниз, коли вони закінчені.

Якщо існує можливість отримати запит, який не може виконати жодна кількість обчислювальної потужності, він не повинен зависати там, що працює до нескінченності, і бізнес-процес чекає відповіді на те, що бізнес вважає кінцевою проблемою.


-2

Я не вірю, що код ніколи не містить 100% помилок, оскільки код ніколи не закінчується. Ви завжди можете покращити те, що пишете.

Програмування - це сфера науки та математики, і те й інше нескінченно. Чудова річ, як бути розробником - це наша робота нескінченна.

Існує тисяча плюс способів написати єдиний рядок коду. Ідея полягає в тому, щоб написати найбільш оптимізовану версію цього рядка коду, але це не може бути помилкою. Безкоштовна помилка посилається на ідею, що ваш код непорушний і весь код може бути порушений певною мірою або методом.

Тож чи може код бути ефективним? Так.
Чи можна оптимізувати код нескінченно? Так.
Чи можна код помилку безкоштовно? Ні, ви просто ще не знайшли способу її зламати.
Якщо говорити, якщо ви прагнете покращити себе та свою практику написання коду, ваш код буде важко порушити.


цю публікацію досить важко читати (стіна тексту). Ви б не хотіли відредагувати його в кращій формі?
гнат
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.