Як ми можемо бути впевнені, що нижні компоненти комп’ютерного програмування, такі як компілятори, асемблери, інструкції з машин тощо, є бездоганними?


57

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

Більш технічно, як перевіряються компілятори та збирачі? (Я вважаю, що це стосується проблеми зупинки !!)


36
Можливо, ви захочете почати свої дослідження з "Кен Томпсона Хак" Дивіться роздуми про довіру довіри
Брайан Оуклі

7
Ось приклад компілятора, для якого є доказ коректності: compcert.inria.fr/doc/index.html
Giorgio

8
Більшість компіляторів / лінкерів / асемблерів тестуються найбільш глибоко, використовуючи їх у багатьох різних обставинах. Для пошуку помилок, нічого вище, ніж мільйони користувачів, які використовують ваш компілятор.
Барт ван Іґен Шенау

3
і також додайте Операційну систему до списку.
Ерік Ейдт

Відповіді:


104

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

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

SQLite складається з близько 73k рядків коду, тоді як його тестовий набір складається з приблизно 91378k рядків коду, що більше ніж у 1250 разів більше, ніж у самого SQLite. Я очікую, що компілятори та інші основні інструменти мають подібні співвідношення. Сьогодні процесори розроблені в основному з програмним забезпеченням, використовуючи такі описи апаратних засобів, як Verilog або VHDL, і на них також проводяться програмні тести програмного забезпечення, а також спеціалізовані IO-штифти для запуску самотестів на місці виготовлення.

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


7
Я часто задавався тим же питанням, що і до ОП, але щодо СУБД. Ви навели чудовий приклад, який відповів на це в контексті SQLite. Дякую!
Брендон

7
+1, але я якось сумніваюся, що "компілятори та інші основні інструменти мають подібні співвідношення".
Мехрдад

5
Зауважте, що (1) SQLite насправді має два тестових набори, з нетривіальним надмірністю між двома та (2) такими помилками в SQLite є незважаючи на це.
Матьє М.

7
У мене склалося враження, що SQLite - це один із найбільш «випробуваних» фрагментів програмного забезпечення (з точки зору рядків тестового коду / рядків операційного коду), доступних для загального використання, тим більше, що навіть багато компіляторів. Якщо нічого іншого, повнофункціональний компілятор - це величезна частина програмного забезпечення, і я не можу собі уявити, щоб він у тисячу разів перевищував кількість тестового коду. (Як повідомляється, до 14,5 мільйонів рядків GCC здається малоймовірним, що або власна колекція компілятора становить лише 14 КБ LOC, або те, що вони мають 14-мільярдну кодову базу тестування на боці !:-P)
David Z

2
@DavidZ: Це, безумовно, єдиний проект, про який я знаю, наприклад, використовую розширене тестування OOM (вони використовують тест-інжектор для тесту і повторно відтворюють їх знову і знову не вдається при першому, а потім у другому виділенні ... до усього тесту виконується).
Матьє М.

46

Простіше кажучи:

  1. Ти не можеш.
  2. Компілятори та перекладачі проходять перевірку на одиниці, як і будь-яке інше (професійне) програмне забезпечення.
  3. Успішний тест не означає, що програма не містить помилок, це означає лише, що помилок не виявлено.
  4. Широка база користувачів, що використовує компілятор протягом тривалого часу, є досить показовим фактом, що він має дуже мало помилок, оскільки користувачі зазвичай перевіряють випадки, про які дизайнери не думали.
  5. Бути відкритим кодом - також хороший показник. "Враховуючи достатню кількість очних яблук, всі помилки дрібні ... Враховуючи достатньо велику бета-тестер та базу для спільних розробників, майже кожна проблема буде охарактеризована швидко і виправлення буде комусь очевидним". . Компілятор із закритим кодом може мати помилки, які виникають у дуже конкретні часи або генерують менш оптимальний машинний код, і компанія, що стоїть за ним, просто не може розкрити своє існування, оскільки надасть йому дуже низький пріоритет у дорожній карті продукту.

Нижня лінія:

Я б сказав, піти на OOP ( O ld, O pen і P opular). Я просто склав цю абревіатуру.


19
+1 Для того, щоб винайти ще один TLA (абревіатура з трьох літер) - у світі ще недостатньо таких.
s1lv3r

34
Також OOP ще не мав значення в комп'ютерному програмуванні. Тож KTT (кудо тобі)!
П'єр Арло

15
Коментар П'єра - це жарт @Dannnno.
янніс

19
Як альтернативи, він може Р популярних ий, Про Л.Д., і виведення пера. ;) Насправді саме так я б класифікував їх за важливістю.
jpmc26

23
@ jpmc26 Я б поїхав із Практичні, Старі, Відкриті та Популярні. Щодо абревіатури ...
StupidOne

24

Це черепахи аж донизу.

Нічого не визначено. У вас немає іншого вибору, як погодитися на рейтингах довіри.

Ви можете вважати це стеком: Math> Physics> Hardware> Прошивка> Операційна система> Assembler / Compiler / тощо

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

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

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

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


17

Це "небезпечне" питання для нових розробників в тому, що вони почнуть звинувачувати свої інструменти замість коду (там, зробили це, бачили, що занадто багато це роблять). Хоча в компіляторах, середовищах виконання, ОС тощо є помилки, розробники повинні бути реалістичними і пам’ятати, що, поки не з’являться докази та одиничні тести, що демонструють інше, помилка знаходиться у вашому коді .

За 25+ років програмування в основному на C, C ++ та Java я виявив:

  • дві помилки через помилку компілятора (gcc та SunOS C)
  • приблизно раз на рік або два помилки через проблему Java JVM (зазвичай пов’язану із споживанням пам'яті / вивезенням сміття)
  • приблизно раз на місяць або два помилки в бібліотеці, які часто виправляються за допомогою останньої версії або повернення до попередньої версії бібліотеки

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


Мені цікаво - на які роки для яких мов? Ще за дні EGCS до того, як C ++ був належним чином стандартизований, помилок компілятора знайти не так складно ...
Чарльз Даффі

3
Чим більше затьмарений компілятор, процесор чи мова, тим легше, тому знайдіть помилку в компіляторах (раніше, ніж хтось інший), тож знайти 2 в GCC C приємно :)
Surt

1
Як це буває, я лише витрачав близько місяця, припускаючи, що проблема, яка виникає в моїх сценаріях gdb, або моє розуміння того, що я вивчав. Врешті-решт я став підозрілим, спростив свій тестовий випадок і виявив ваду дизайну в бібліотеці (libkvm), яка зробила налагоджувач ядра не в змозі отримати доступ до певних адрес з основного дампа. Тобто YMMV - і я найщасливіший, коли знаходжу нову помилку в коді вище за мене, особливо те, що я використовую, а не розвиваю.
Арлі Стівенс

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

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

8

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

ПРОГРАМНЕ ЗАБЕЗПЕЧЕННЯ надається "ЯК Є Є", БЕЗ ГАРАНТІЇ БУДЬ-ЯКОГО РОЗУМУ, ЕКСПРЕССУ АБО НЕ ВПРАВЛЕНО, Включаючи НЕ ОБМЕЖЕНІ ГАРАНТІЯМИ ПРОДАЖНОСТІ, ФІТНІСНОСТІ ДЛЯ ЧАСНОГО МЕТА І НЕФІНФОРМУВАННЯ.

З ліцензійної угоди Microsoft Word

. За винятком Обмеженої гарантії та в максимальній мірі, дозволеній чинним законодавством, Microsoft та її постачальники надають Програмне забезпечення та послуги підтримки (якщо такі є) ЯК Є І З ВСІМИ НЕПРАВИМИМИ, і цим відмовляються від усіх інших гарантій та умов, будь то явні, маються на увазі чи встановлені законодавством, включаючи, але не обмежуючись ними, будь-які (якщо такі є) маються на увазі гарантії, обов'язки або умови товарності, придатності до певної мети, надійності чи доступності, точності чи повноти відповідей, результатів, зусиль, що виконуються робочими силами, відсутність вірусів і відсутність недбалості, що стосується Програмного забезпечення, а також надання або ненадання підтримки чи інших послуг, інформації, програмного забезпечення та відповідного вмісту через Програмне забезпечення або іншим чином, що виникає внаслідок використання Програмного забезпечення .

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

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


+1 за вказівку, що самі ліцензії стверджують, що жодне програмне забезпечення не є досконалим.
Tulains Córdova

3
Мені було приємно відзначити відхилення від цієї практики в ViaVoice для Mac від IBM. Замість звичного "якщо це не працює, занадто погано", вони насправді сказали щось на кшталт "Програмне забезпечення гарантовано виконувати як зазначено".
WGroleau

1
Простий переклад цього конкретного фрагмента гарантійного фразування є: "Це може бути програмне забезпечення, або це може бути шматок. Це може спрацювати. Можливо, це не буде. Навіть якщо це працює, можливо, це не буде робіть те, що ви хочете. О, до речі, ми могли б вкрасти шматочки у когось іншого. Шкода, що ми отримали ваші гроші і використали їх для наймання багатьох адвокатів. -нях-нях-няах-наа! ". :-)
Боб Джарвіс

2
@BobJarvis: Моя улюблена гарантійна заява, яка використовується на деякому програмному забезпеченні з відкритим кодом (наприклад, nmap IIRC), - "Якщо вона зламається, ви можете зберегти обидві частини".
Пітер Кордес

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

2

Як автор-компілятор для математичної мови *, зі свого досвіду я можу сказати, що теоретично ви не можете. А деякі помилки дають неправильні результати, як-от (зі свого списку сорому), обчислюючи 6/3*2праворуч 6/(3*2)і виводячи 1, не врізаючись або не даючи безглуздих помилок компіляції.

Але IMHO у багатьох компіляторів не має такої кількості помилок, як у іншого програмного забезпечення, оскільки:

  • Писати одиничні тести легко. Кожне твердження є одиницею, і ви можете писати тести так само просто:test_unit("2+(-2)*(-2+1)*3+1",9);
  • Програма - це комбінація висловлювань, і для будь-якої програми для виведення правильного результату кожне окреме твердження повинно дати правильний результат (здебільшого). Тому навряд чи виникнуть помилки, коли програма дає правильний результат.
  • Зі збільшенням розміру та кількості написаних програм ймовірність попадання помилок різко зростає.

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

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

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

Моя скромна мова з математики *


Intel випробовує пекло своїх процесорів, виконуючи послідовності випадкових інструкцій та порівнюючи із програмною моделлю, серед іншого: tweakers.net/reviews/740/4/… . Ось чому ви часто бачите справді незрозумілі помилки, опубліковані для дійсно малоймовірних комбінацій інструкцій у незвичному режимі.
Пітер Кордес

0

Бездоганний? Їх немає. Нещодавно я встановив деякі "оновлення", і пішло місяці (і кілька перепрограмованих розділів коду), перш ніж мій сайт ASP.NET знову працював належним чином, через незрозумілі зміни в тому, як різні базові речі працювали чи не працювали.

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

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


-1

Щоб показати, що базові системи є бездоганними і ви

а) Необхідно довести, що вони бездоганні

  1. Математичне доведення
  2. Тільки реально можливо для тривіальних програм

б) Зробіть вичерпний тест

  1. Можливе лише для тривіальних програм та деяких простих програм
  2. Як тільки елемент хронометражу входить до випробування, неможливо зробити вичерпний тест, оскільки час можна нескінченно розділити.
  3. Поза тривіальними програмами можливі варіанти виконання вибухають експоненціально.

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

Приклад: Ви хочете перевірити вхід 8-символу utf-8 до якогось поля, ви вирішите вирізати вхід у 8 разів більше максимальної довжини 6 utf-8 у байтах, що дає 8 * 6 = 48 байт, щоб насправді мати а обмеженість можливостей.

Тепер ви могли подумати, що потрібно лише протестувати 1,112,064 дійсних кодових точок кожного з 8 символів, тобто. 1,112,064 ^ 8 (скажімо, 10 ^ 48) тестів (що навряд чи можливо), але ви насправді повинні перевірити кожне значення кожного з 48 байтів або 256 ^ 48, що становить близько 10 ^ 120, що є такою ж складністю, як і шахи. порівняно із загальною кількістю атомів у Всесвіті приблизно 10 ^ 80.

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

а) перевірити хороший і поганий зразок.

б) покриття коду, тобто. спробуйте перевірити кожен рядок коду, що для більшості кодів відносно просто. Тепер ви можете задатись питанням про те, що останні 1% коду, який ви не можете перевірити, є ... помилки, мертвий код, винятки з обладнання тощо.

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

г) перевірка даних, випробування кількості вибірки з граничним значенням, загальними проблемними значеннями та магічними числами, нулем, -1, 1, хв +/- 1, макс +/- 1, 42, rnd значеннями. Якщо це не дає вам покриття шляху, ви знаєте, що ви не знайшли всіх значень у своєму аналізі.

Якщо ви це вже робите, ви повинні бути готові до іспиту з фундаментальної іспит ISTQB.

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