Может ли оптимизация компилятора вводить ошибки? - PullRequest
68 голосов
/ 27 апреля 2010

Сегодня у меня была беседа с моим другом, и мы пару часов обсуждали «оптимизацию компилятора».

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

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

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

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

Ответы [ 23 ]

4 голосов
/ 27 апреля 2010

Псевдоним может вызвать проблемы с определенными оптимизациями, поэтому у компиляторов есть возможность отключить эти оптимизации. От Википедия :

Чтобы обеспечить такую ​​оптимизацию предсказуемым образом, стандарт ISO для языка программирования C (включая его более новую версию C99) указывает, что указатели разных типов недопустимы (за некоторыми исключениями) для ссылки на одну и ту же ячейку памяти. Это правило, известное как «строгий псевдоним», допускает впечатляющее увеличение производительности [необходима цитата], но известно, что оно нарушает какой-то другой действительный код. Несколько программных проектов намеренно нарушают эту часть стандарта C99. Например, Python 2.x сделал это, чтобы реализовать подсчет ссылок [1], и потребовал внести изменения в базовые структуры объектов в Python 3, чтобы включить эту оптимизацию. Ядро Linux делает это, потому что строгое псевдонимы вызывают проблемы с оптимизацией встроенного кода. [2] В таких случаях при компиляции с помощью gcc опция -fno-strict-aliasing вызывается для предотвращения нежелательных или недопустимых оптимизаций, которые могут привести к неправильному коду.

3 голосов
/ 27 апреля 2010

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

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

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

2 голосов
/ 27 апреля 2010

Я, конечно, согласен, что глупо говорить, потому что "умные люди" пишут компиляторы, что они поэтому безошибочны. Умные люди тоже спроектировали Гинденберг и Мост Такомы. Даже если это правда, что составители компиляторов являются одними из самых умных программистов, это также верно, что компиляторы являются одними из самых сложных программ. Конечно, у них есть ошибки.

С другой стороны, опыт подсказывает нам, что надежность коммерческих компиляторов очень высока. У меня было много раз, когда кто-то говорил мне, что причина, по которой программа не работает, ДОЛЖНА быть из-за ошибки в компиляторе, потому что он очень тщательно ее проверил и уверен, что она на 100% верна и тогда мы обнаруживаем, что на самом деле программа имеет ошибку, а не компилятор. Я пытаюсь вспомнить времена, когда я лично сталкивался с чем-то, что, я был действительно уверен, было ошибкой в ​​компиляторе, и я могу вспомнить только один пример.

В общем: доверяйте своему компилятору. Но они когда-нибудь ошибаются? Конечно.

2 голосов
/ 27 апреля 2010

Это может случиться. Это даже затронуло Linux .

2 голосов
/ 27 апреля 2010

Это теоретически возможно, конечно. Но если вы не доверяете инструментам делать то, что они должны делать, зачем их использовать? Но сразу любой, кто спорит с позиции

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

приводит глупый аргумент.

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

1 голос
/ 30 апреля 2012

У меня была проблема в .NET 3.5, если вы строите с оптимизацией, добавьте в метод еще одну переменную, которая называется аналогично существующей переменной того же типа в той же области видимости, что и одна из двух (новая или старая переменная) ) будет недействительным во время выполнения, и все ссылки на недопустимую переменную будут заменены ссылками на другую.

Так, например, если у меня есть abcd типа MyCustomClass и у меня есть abdc типа MyCustomClass, и я установил abcd.a = 5 и abdc.a = 7, тогда обе переменные будут иметь свойство a = 7. Чтобы решить эту проблему, обе переменные должны быть удалены, программа скомпилирована (надеюсь, без ошибок), затем они должны быть добавлены заново.

Я думаю, что несколько раз сталкивался с этой проблемой при работе с .NET 4.0 и C # при работе с приложениями Silverlight. На моей последней работе мы часто сталкивались с проблемой в C ++. Возможно, это произошло из-за того, что компиляция заняла 15 минут, поэтому мы собирали только те библиотеки, которые нам были нужны, но иногда оптимизированный код был точно таким же, как и в предыдущей сборке, даже если был добавлен новый код и об ошибках сборки не сообщалось. *

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

1 голос
/ 03 июня 2016

Оптимизация компилятора может выявить (или активировать) неактивные (или скрытые) ошибки в вашем коде. В вашем C ++-коде может быть ошибка, о которой вы не знаете, просто не видите ее. В этом случае это скрытая или неактивная ошибка, потому что эта ветвь кода не выполняется [достаточное количество раз].

Вероятность ошибки в вашем коде намного больше (в тысячи раз больше), чем ошибка в коде компилятора: потому что компиляторы тщательно протестированы. К плюсам TDD практически все люди, которые используют их с момента их выпуска!). Поэтому вряд ли вы обнаружите ошибку, а не обнаружите ее буквально сотнями тысяч раз, когда она используется другими людьми.

неактивная ошибка или скрытая ошибка - это просто ошибка, которая еще не раскрыта программисту. Люди, которые могут утверждать, что в их коде C ++ нет (скрытых) ошибок, встречаются очень редко. Это требует знаний C ++ (на это могут претендовать очень немногие) и тщательного тестирования кода. Речь идет не только о программисте, но и о самом коде (стиль разработки). Склонность к ошибкам заключается в характере кода (насколько он проверен) или / и программиста (насколько дисциплинирован в тестировании и насколько хорошо знают C ++ и программирование).

Безопасность + ошибки параллелизма: это еще хуже, если мы включаем параллелизм и безопасность в качестве ошибок. Но в конце концов, это «ошибки». Написание кода, который в первую очередь не содержит ошибок с точки зрения параллелизма и безопасности, практически невозможен. Поэтому в коде всегда есть ошибка, которую можно обнаружить (или забыть) при оптимизации компилятора.

1 голос
/ 28 апреля 2010

Насколько я помню, в ранней версии Delphi 1 была ошибка, из-за которой результаты Min и Max были изменены на противоположные. Была также неясная ошибка с некоторыми значениями с плавающей запятой, только когда значение с плавающей запятой использовалось в dll. По общему признанию, это было больше чем десятилетие, таким образом, моя память может быть немного нечеткой.

0 голосов
/ 13 ноября 2018

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

#pragma optimize( "", off)

(Мы используем Microsoft Visual C ++ native, 2015, но это верно практически для любого компилятора, за исключением, возможно, Intel Fortran 2016, обновление 2, где мы еще не отказались от каких-либо оптимизаций.)

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

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

0 голосов
/ 30 апреля 2016

У меня вчера была проблема с .net 4 с чем-то похожим на ...

double x=0.4;
if(x<0.5) { below5(); } else { above5(); }

И это будет называть above5(); Но если я на самом деле где-то использую x, это будет называть below5();

double x=0.4;
if(x<0.5) { below5(); } else { System.Console.Write(x); above5(); }

Не тот же код, но похожий.

...