Мы ежедневно используем компиляторы, как если бы их корректность была задана, но компиляторы тоже являются программами и могут содержать ошибки Я всегда задавался вопросом об этой непогрешимой надежности. Вы когда-нибудь сталкивались с ошибкой в самом компиляторе? Что это было и как вы поняли, что проблема была в самом компиляторе?
... и как же они делают компиляторы настолько надежны?
testing
bug
compiler
system-reliability
EpsilonVector
источник
источник
Ответы:
Они проходят тщательное тестирование через тысячи и даже миллионы разработчиков.
Кроме того, проблема, которая должна быть решена, хорошо определена (очень подробным техническим описанием). И характер задачи легко поддается модульным / системным тестам. Т.е. это в основном перевод текстового ввода в очень специфическом формате для вывода в другом четко определенном формате (некоторый вид байт-кода или машинного кода). Так что легко создавать и проверять контрольные примеры.
Более того, обычно ошибки также легко воспроизводятся: кроме точной информации о платформе и версии компилятора, обычно все, что вам нужно, это фрагмент входного кода. Не говоря уже о том, что пользователи компилятора (сами разработчики), как правило, предоставляют гораздо более точные и подробные отчеты об ошибках, чем любой обычный пользователь компьютера :-)
источник
В дополнение ко всем отличным ответам пока:
У вас есть "предвзятость наблюдателя". Вы не видите ошибок, и поэтому вы предполагаете, что их нет.
Я привык думать, как ты. Затем я начал профессионально писать компиляторы, и позвольте мне сказать вам, что там много ошибок!
Вы не видите ошибок, потому что вы пишете код, который составляет 99,999% от всего остального кода, который пишут люди. Вы, вероятно, пишете совершенно нормальный, простой, четко корректный код, который вызывает методы и запускает циклы и не делает ничего фантастического или странного, потому что вы обычный разработчик, решающий обычные бизнес-задачи.
Вы не видите никаких ошибок компилятора, потому что ошибки компилятора не в простых для анализа простых сценариях нормального кода; ошибки заключаются в анализе странного кода, который вы не пишете.
У меня, с другой стороны, есть противоположный уклон наблюдателя. Я вижу сумасшедший код весь день каждый день, и поэтому мне кажется, что компиляторы переполнены ошибками.
Если вы сели со спецификацией языка любого языка и взяли любую реализацию компилятора для этого языка, и действительно изо всех сил пытались определить, точно ли компилятор реализовал спецификацию или нет, концентрируясь на неясных угловых случаях, довольно скоро вы найдете ошибки компилятора довольно часто. Позвольте мне привести пример, вот ошибка компилятора C #, которую я обнаружил буквально пять минут назад.
Компилятор выдает три ошибки.
Очевидно, что первое сообщение об ошибке является правильным, а третье - ошибкой. Алгоритм генерации ошибок пытается выяснить, почему первый аргумент был недействительным, он просматривает его, видит, что он является константой, и не возвращается к исходному коду, чтобы проверить, был ли он помечен как «ref»; скорее он предполагает, что никто не будет достаточно глуп, чтобы пометить константу как ref, и решает, что ссылка должна отсутствовать.
Непонятно, каково правильное третье сообщение об ошибке, но это не так. На самом деле, не ясно, правильно ли второе сообщение об ошибке. Должно ли разрешение перегрузки завершиться неудачно, или «ref 123» должен рассматриваться как аргумент ref правильного типа? Теперь мне нужно подумать и обсудить это с командой по сортировке, чтобы мы могли определить правильное поведение.
Вы никогда не видели эту ошибку, потому что вы, вероятно, никогда бы не сделали что-то настолько глупое, чтобы попытаться передать 123 по ссылке. И если бы вы это сделали, вы, вероятно, даже не заметили бы, что третье сообщение об ошибке бессмысленно, поскольку первое является правильным и достаточным для диагностики проблемы. Но я стараюсь делать такие вещи, потому что я пытаюсь сломать компилятор. Если бы вы попробовали, вы бы тоже увидели ошибки.
источник
Ты шутишь, что ли? Компиляторы тоже имеют ошибки, действительно загружаются.
GCC, пожалуй, самый знаменитый компилятор с открытым исходным кодом на планете, и взгляните на его базу данных ошибок: http://gcc.gnu.org/bugzilla/buglist.cgi?product=gcc&component=c%2B%2B&resolution=-- -
Между GCC 3.2 и GCC 3.2.3 посмотрите, сколько ошибок исправлено: http://gcc.gnu.org/gcc-3.2/changes.html
Что касается других, таких как Visual C ++, я даже не хочу начинать.
Как вы делаете компиляторы надежными? Хорошо для начала у них есть грузы и грузы модульных тестов. И вся планета использует их, поэтому нет недостатка в тестерах.
Если серьезно, то разработчики компиляторов, которым я хотел бы верить, являются превосходными программистами, и, хотя они не являются непогрешимыми, они делают все возможное.
источник
Я столкнулся с двумя или тремя в мой день. Единственный реальный способ обнаружить это - посмотреть на ассемблерный код.
Хотя компиляторы очень надежны по причинам, указанным другими авторами, я думаю, что надежность компилятора часто является самоокупаемой оценкой. Программисты склонны рассматривать компилятор как стандарт. Когда что-то идет не так, вы полагаете, что это ваша ошибка (потому что это 99,999% времени), и изменяете свой код, чтобы обходить проблему с компилятором, а не наоборот. Например, сбой кода при высокой настройке оптимизации, безусловно, является ошибкой компилятора, но большинство людей просто устанавливают ее немного ниже и продолжают работу, не сообщая об ошибке.
источник
Компиляторы имеют несколько свойств, которые приводят к их корректности:
источник
Они не Мы делаем. Поскольку все используют их постоянно, ошибки обнаруживаются быстро.
Это игра чисел. Поскольку компиляторы используются повсеместно, весьма вероятно, что любая ошибка будет вызвана кем-то, но из-за такого большого количества пользователей весьма маловероятно , что кто-то будет именно вами.
Таким образом, это зависит от вашей точки зрения: у всех пользователей компиляторы глючат. Но очень вероятно, что кто-то другой скомпилирует подобный кусок кода раньше, чем вы, поэтому, если бы это была ошибка, он бы поразил их, а не вас, поэтому, с вашей индивидуальной точки зрения, похоже, что ошибка была никогда там.
Конечно, помимо этого, вы можете добавить все остальные ответы здесь: компиляторы хорошо изучены, хорошо поняты. Существует миф о том, что их трудно писать, а это означает, что только очень умные, очень хорошие программисты на самом деле пытаются его написать, и при этом они особенно осторожны. Как правило, их легко тестировать, а также стресс-тест или фазз-тест. Пользователи компиляторов, как правило, сами являются опытными программистами, что приводит к высококачественным сообщениям об ошибках. И наоборот: авторы компиляторов, как правило, являются пользователями своего собственного компилятора.
источник
В дополнение ко всем ответам, я хотел бы добавить:
Я верю , что продавцы часто едят свою собачью еду. Это означает, что они пишут компиляторы сами по себе.
источник
Я часто сталкиваюсь с ошибками компилятора.
Вы можете найти их в темных углах, где меньше тестеров. Например, чтобы найти ошибки в GCC, вы должны попробовать:
источник
Некоторые причины:
источник
Они обычно очень хороши в -O0. Фактически, если мы подозреваем ошибку компилятора, мы сравниваем -O0 с тем уровнем, который мы пытаемся использовать. Более высокие уровни оптимизации идут с большим риском. Некоторые даже намеренно так и обозначены как таковые в документации. Я встречал очень много (по крайней мере, сотню в мое время), но в последнее время они становятся все более редкими. Тем не менее, в погоне за хорошими показателями (или другими важными для маркетинга ориентирами) соблазн раздвинуть границы велик. У нас были проблемы несколько лет назад, когда вендор (чтобы остаться неназванным) решил сделать нарушение скобок по умолчанию - больше, чем какой-то особый явно помеченный параметр компиляции.
Может быть трудно диагностировать ошибку компилятора по сравнению, скажем, с ошибочной ссылкой на память, перекомпиляция с различными опциями может просто зашифровать относительное расположение объектов данных в памяти, поэтому вы не знаете, является ли это исходным кодом Heisenbug или ошибкой компилятор. Также многие оптимизации вносят законные изменения в порядок операций или даже алгебраические упрощения в вашей алгебре, и они будут иметь различные свойства в отношении округления с плавающей запятой и недостаточного / переполнения. Трудно отделить эти эффекты от РЕАЛЬНЫХ ошибок. По этой причине жесткие вычисления с плавающей запятой сложны, потому что ошибки и численная чувствительность часто нелегко распутать.
источник
Ошибки компилятора не так уж редки. Наиболее распространенным случаем является то, что компилятор сообщает об ошибке в коде, который должен быть принят, или для компилятора, чтобы принять код, который должен был быть отклонен.
источник
Да, я столкнулся с ошибкой в компиляторе ASP.NET только вчера:
При использовании строго типизированных моделей в представлениях существует ограничение на количество шаблонов параметров. Очевидно, что он не может принимать более 4 параметров шаблона, поэтому оба приведенных ниже примера делают его слишком сложным для обработки компилятором:
Не будет компилироваться как есть, но будет, если
type5
удаляется.Скомпилирует, если
type4
будет удален.Обратите внимание, что он
System.Tuple
имеет много перегрузок и может принимать до 16 параметров (я знаю, это безумие).источник
Ага!
Два самых запоминающихся были первые два, с которыми я столкнулся. Они оба были в компиляторе Lightspeed C для компьютеров Mac 680x0 примерно в 1985-7 годах.
Первый случай, когда при некоторых обстоятельствах целочисленный постинкрементный оператор ничего не делал - другими словами, в определенном фрагменте кода «i ++» просто ничего не делал с «i». Я вырывал свои волосы, пока не посмотрел на разборку. Затем я просто сделал инкремент и отправил отчет об ошибке.
Второй был немного сложнее, и это была действительно непродуманная «фишка», которая пошла наперекосяк. Ранние Mac имели сложную систему для выполнения операций с дисками низкого уровня. По какой-то причине я никогда не понимал - вероятно, из-за создания меньших исполняемых файлов - вместо того, чтобы компилятор просто генерировал инструкции по работе с диском на месте в объектном коде, компилятор Lightspeed будет вызывать внутреннюю функцию, которая во время выполнения генерировала операцию на диске Инструкция по стеку и там прыгнул.
Это прекрасно работает на 68000 процессорах, но когда вы запускаете один и тот же код на 68020 процессорах, это часто приводит к странным вещам. Оказалось, что новой особенностью 68020 стал кэш инструкций 256-байтовых примитивов. Начиная с первых дней работы с кешами ЦП, он не имел представления о том, что кэш «грязный» и нуждается в пополнении; Я думаю, что разработчики процессоров в Motorola не думали о самом изменяющемся коде. Таким образом, если вы выполнили две дисковые операции достаточно близко друг к другу в своей последовательности выполнения, и среда выполнения Lightspeed создала фактические инструкции в одном и том же месте в стеке, ЦП ошибочно подумал бы, что получил удар по кэшу инструкций, и дважды выполнил первую операцию на диске.
Опять же, чтобы понять это, нужно было покопаться с дизассемблером и немало пошаговых действий в отладчике низкого уровня. Мой обходной путь состоял в том, чтобы поставить перед каждой дисковой операцией префикс с вызовом функции, которая выполняла 256 «NOP» инструкций, которые заполняли (и таким образом очищали) кэш инструкций.
За 25 лет с тех пор я видел все меньше и больше ошибок компилятора. Я думаю, что есть несколько причин для этого:
источник
Нашел явную ошибку в Turbo Pascal 5,5 лет назад. Ошибка присутствует ни в предыдущей (5.0), ни в следующей (6.0) версии компилятора. И тот, который должен был быть легко протестирован, так как он вообще не был угловым (просто вызов, который не так часто используется).
В общем, конечно, коммерческие сборщики компиляторов (а не хобби-проекты) будут иметь очень обширные процедуры обеспечения качества и тестирования. Они знают, что их компиляторы являются их ведущими проектами, и что недостатки будут выглядеть для них очень плохо, хуже, чем для других компаний, производящих большинство других продуктов. Разработчики программного обеспечения - неумолимая куча, наши поставщики инструментов подводят нас, что мы, скорее всего, пойдем искать альтернативы, а не ждем исправления от поставщика, и мы, скорее всего, сообщим об этом факте нашим коллегам, которые вполне могут последовать нашему пример. Во многих других отраслях это не так, поэтому потенциальные убытки для производителя компиляторов в результате серьезной ошибки намного больше, чем, скажем, для производителя программного обеспечения для редактирования видео.
источник
Когда поведение вашего программного обеспечения отличается при компиляции с -O0 и с -O2, вы обнаружили ошибку компилятора.
Когда поведение вашего программного обеспечения отличается от ожидаемого, есть вероятность, что ошибка в вашем коде.
источник
Ошибки компиляции случаются, но вы склонны находить их в нечетных углах ...
В 1990-х годах в компиляторе VAX VMS C компании Digital Equipment была странная ошибка
(Я был одет в лук на поясе, как это было в то время)
Внешняя точка с запятой в любом месте, предшествующем циклу for, будет скомпилирована как тело цикла for.
В рассматриваемом компиляторе цикл выполняется только один раз.
это видит
Это стоило мне много времени.
Старая версия компилятора PIC C, которую мы (раньше) применяли к опыту работы, не могла генерировать код, который правильно использовал прерывание с высоким приоритетом. Вам пришлось ждать 2-3 года и обновляться.
В компиляторе MSVC 6 была изящная ошибка в компоновщике, это могло привести к ошибке сегментации и время от времени умирать без причины. Чистая сборка вообще исправляла это (но вздыхает не всегда).
источник
В некоторых областях, таких как программное обеспечение для авионики, предъявляются чрезвычайно высокие требования к сертификации как для кода, так и для оборудования, а также для компилятора. Об этой последней части есть проект, который направлен на создание формально проверенного компилятора C под названием Compcert . Теоретически, этот тип компилятора так же надежен, как и появился.
источник
Я видел несколько ошибок компилятора, сообщал о нескольких сам (в частности, в F #).
Тем не менее, я думаю, что ошибки компилятора редки, потому что люди, которые пишут компиляторы, как правило, очень довольны строгими концепциями компьютерной науки, которые заставляют их по-настоящему осознавать математические последствия кода.
Большинство из них, по-видимому, очень хорошо знакомы с такими вещами, как лямбда-исчисление, формальная проверка, денотационная семантика и т. Д. - вещи, которые обычный программист, такой как я, может понять только с трудом.
Кроме того, в компиляторах обычно довольно простое отображение входных и выходных данных, поэтому отладка языка программирования, вероятно, намного проще, чем, например, отладка движка блога.
источник
Я нашел ошибку в C # компилятор не так давно, вы можете увидеть , как Эрик Липперт (который находится на C # проектной группы) выяснили , что ошибка была здесь .
В дополнение к уже даным ответам я хотел бы добавить еще несколько вещей. Разработчики компиляторов часто очень хорошие программисты. Компиляторы очень важны: большинство программ выполняется с использованием компиляторов, поэтому обязательно, чтобы компилятор был высокого качества. Поэтому в интересах компаний, производящих компиляторы, ставить на это своих лучших людей (или, по крайней мере, очень хороших: лучшим, возможно, не понравится дизайн компилятора). Microsoft очень хотела бы, чтобы их компиляторы C и C ++ работали должным образом, иначе остальная часть компании не может выполнять свою работу.
Кроме того, если вы создаете действительно сложный компилятор, вы не можете просто взломать его вместе. Логика компиляторов очень сложна и проста для формализации. Следовательно, эти программы будут часто создаваться очень «надежно» и обобщенно, что приводит к меньшему количеству ошибок.
источник