Какие из самых неприятных и сложных ошибок вам пришлось отслеживать и исправлять и почему?
Я действительно искренне любопытен и колен в процессе, когда мы говорим. Так что, как говорится, страдание любит компанию.
Какие из самых неприятных и сложных ошибок вам пришлось отслеживать и исправлять и почему?
Я действительно искренне любопытен и колен в процессе, когда мы говорим. Так что, как говорится, страдание любит компанию.
Гейзенбуг (названный в честь принципа неопределенности Гейзенберга) - это компьютерная ошибка, которая исчезает или изменяет ее характеристики при попытке изучить ее.
Условия гонки и тупики. Я делаю много многопоточных процессов, и это труднее всего иметь дело.
Ошибки, возникающие при компиляции в режиме деблокирования, но не в режиме отладки.
Любая ошибка, основанная на условиях синхронизации. Они часто возникают при работе с межпоточной связью, внешней системой, чтением из сети, чтении из файла или общении с любым внешним сервером или устройством.
Ошибки, которые не входят в ваш код как таковой, а скорее в модуле поставщика, от которого вы зависите. В частности, когда продавец не отвечает, и вы вынуждены взламывать работу. Очень расстраивает!
Мы разрабатывали базу данных для хранения слов и определений на другом языке. Оказывается, этот язык недавно был добавлен в стандарт Unicode, и он не попал в SQL Server 2005 (хотя он был добавлен около 2005 года). Это имело очень неприятный эффект, когда дело доходило до сортировки.
Слова и определения прошли очень хорошо, я мог видеть все в Management Studio. Но всякий раз, когда мы пытались найти определение для данного слова, наши запросы ничего не возвращали. После прочного 8-часового отладки я был в состоянии думать, что потерял способность писать простой запрос SELECT.
То есть, пока я не заметил, что английские буквы соответствовали другим английским буквам с любым количеством иностранных букв. Например, EnglishWord будет соответствовать E! n @gl ## $ish $& Слово. (С! @# $% ^ & *, представляющим иностранные буквы).
Когда сортировка не знает об определенном символе, он не может сортировать их. Если он не может их сортировать, он не может определить, соответствуют ли две строки или нет (сюрприз для меня). Настолько разочаровывает и целый день спускает воду из-за глупой настройки сортировки.
Ошибки в потоках, особенно условия гонки. Когда вы не можете остановить систему (потому что ошибка уходит), все быстро становится жестким.
Самые сложные из них, которые я обычно запускаю, - это те, которые не отображаются в любой трассировке журнала. Вы никогда не должны спокойно есть исключение! Проблема в том, что употребление исключения часто переводит ваш код в недопустимое состояние, где он не работает позже в другом потоке и совершенно несвязанным образом.
Тем самым самым сложным из тех, с которыми я когда-либо сталкивался, была программа C в вызове функции, где вызывающая подпись не точно соответствовала вызываемой сигнатуре (одна была длинной, а другая - int). Не было ошибок во время компиляции или времени ссылки, и большинство тестов прошло, но стек был отключен sizeof (int), поэтому переменные после него в стеке случайным образом имели плохие значения, но большую часть времени он работал нормально ( значения, следующие за этим плохим параметром, обычно передавались как ноль).
Это был BITCH для отслеживания.
Повреждение памяти под нагрузкой из-за плохого оборудования.
Наиболее неприятными для меня были ошибки компилятора, где код правильный, но я попал в недокументированный угловой случай или что-то, где компилятор ошибается. Я исхожу из предположения, что я совершил ошибку, а затем провел несколько дней, пытаясь найти его.
Edit: Другим наиболее разочаровывающим было время, когда я получил тестовый пример, немного ошибочный, поэтому мой код был правильным, но теста не было. Это заняло несколько дней, чтобы найти.
В общем, я думаю, худшие ошибки, которые у меня были, были теми, которые не являются моей ошибкой.
Самые трудные ошибки для отслеживания и исправления - это те, которые объединяют все сложные случаи:
На этой неделе я работал над ошибкой со всеми этими функциями. Необходимо было перепрограммировать библиотеку, чтобы узнать, в чем дело; затем генерировать гипотезы о том, какие два устройства участвовали в гонках; затем создайте специально разработанные версии программы, призванные спровоцировать гипотетическое состояние гонки; то, как только одна из гипотез была подтверждена, можно было синхронизировать время событий, чтобы библиотека выиграла гонку в 100% случаев.
Используемые Crystal Reports?
Был проект по созданию химического инженерного тренажера с использованием кластера Beowulf. Так получилось, что сетевые карты не будут передавать одну конкретную последовательность байтов. Если пакет содержит эту строку, пакет будет потерян. Они решили проблему, заменив аппаратное обеспечение - найти его в первую очередь было намного сложнее.
Одна из самых сложных ошибок, которые мне пришлось найти, - ошибка памяти, которая произошла только после того, как программа работала в течение нескольких часов. Из-за продолжительности времени, затраченного на повреждение данных, мы предположили аппаратное обеспечение и попробовали сначала два или три компьютера.
Ошибка появлялась бы несколько часов, и когда она появлялась, ее обычно замечали довольно много времени после того, как программа настолько запуталась, что она начала плохо себя вести. Сужение в базе кода до места возникновения ошибки было очень затруднительным, потому что в функции, которая искажала память, никогда не возникало сбоев из-за поврежденной памяти, и для этой ошибки было так долго пропущено.
Ошибка оказалась ошибочной ошибкой в редко называемой части кода для обработки строки данных, которая с ней что-то неладно (недопустимая кодировка символов из памяти).
В конце концов, отладчик оказался рядом с бесполезным, поскольку в дереве вызовов никогда не возникало сбоев для функции нарушения. Хорошо упорядоченный поток fprintf (stderr,...) вызывает код, а вывод данных в файл - это то, что в конечном итоге позволило нам определить, в чем проблема.
У моей подруги была эта ошибка. Он случайно помещает аргумент функции в программу C в квадратных скобках вместо круглых скобок, например: foo[5]
вместо foo(5)
. Компилятор был совершенно счастлив, потому что имя функции является указателем, и нет ничего незаконного в индексировании указателя.
Одним из самых неприятных для меня было то, что алгоритм был неправильным в спецификации программного обеспечения.
Вероятно, не самые сложные, но они чрезвычайно распространены, а не тривиальны:
Самый сложный из когда-либо был на самом деле ошибкой, с которой я помогал другу. Он писал C в MS Visual Studio 2005 и забыл включить time.h. Он далее называл время без необходимого аргумента, обычно NULL. Это неявно объявленное время: int time(); Это исказило стек и совершенно непредсказуемым образом. Это был большой код, и мы не думали долго смотреть на вызов time().
Concurrency ошибки довольно сложно отслеживать, потому что их воспроизведение может быть очень тяжело, когда вы еще не знаете, что такое ошибка. Поэтому каждый раз, когда вы видите необъяснимую трассировку стека в журналах, вы должны искать причину этого исключения, пока не найдете его. Даже если это происходит только один раз в миллион, это не делает его несущественным.
Поскольку вы не можете полагаться на тесты для воспроизведения ошибки, вы должны использовать дедуктивные рассуждения, чтобы узнать об ошибке. Это, в свою очередь, требует глубокого понимания того, как работает система (например, как работает модель памяти Java и какие возможные источники ошибок concurrency).
Вот пример ошибки concurrency в Guice 1.0, который я нашел всего несколько дней назад. Вы можете проверить свои навыки поиска ошибок, пытаясь выяснить, что такое ошибка, вызывающая это исключение. Ошибка найти не так сложно - я нашел ее причину примерно через 15-30 минут (ответ здесь).
java.lang.NullPointerException
at com.google.inject.InjectorImpl.injectMembers(InjectorImpl.java:673)
at com.google.inject.InjectorImpl$8.call(InjectorImpl.java:682)
at com.google.inject.InjectorImpl$8.call(InjectorImpl.java:681)
at com.google.inject.InjectorImpl.callInContext(InjectorImpl.java:747)
at com.google.inject.InjectorImpl.injectMembers(InjectorImpl.java:680)
at ...
P.S. Неисправное оборудование может вызвать даже более неприятные ошибки, чем concurrency, потому что это может занять много времени, прежде чем вы сможете уверенно заключить, что в коде нет ошибок. К счастью аппаратные ошибки реже, чем программные ошибки.
Переполнение буфера (в собственном коде)
В прошлом году я провел пару месяцев, отслеживая проблему, которая оказалась ошибкой в нисходящей системе. Команда привела к тому, что система оскорблений заявила, что она должна быть чем-то смешным в нашей обработке, хотя мы передали данные так же, как они просили ее у нас. Если бы лидерство было бы немного более кооперативным, мы могли бы пригвоздить ошибку раньше.
Неинициализированные переменные. (Или современные языки покончили с этим?)
Сложность отслеживания:
Когда объекты кэшируются, а их реализации equals и hashcode реализованы так плохо, что значение хеш-кода не является уникальным, а equals возвращает true, когда оно не равно.
Проблемы, зависящие от машины.
В настоящее время я пытаюсь отлаживать, почему приложение имеет необработанное исключение в блоке try {} catch {} (да, необработанном внутри try/catch), который проявляется только в некоторых сборках OS/machine, а не в другие.
Такая же версия программного обеспечения, тот же установочный носитель, тот же исходный код, работает над некоторым - необработанным исключением в том, что должно быть очень хорошо обработанной частью кода для других.
Гак.
Косметические веб-ошибки, включающие стилизацию в различных конфигурациях O/S браузера, например. страница отлично выглядит в Windows и Mac в Firefox и IE, но на Mac в Safari что-то перепуталось. Иногда это раздражает, потому что они требуют такого большого внимания к деталям и изменения, которые нужно исправить. Safari может сломать что-то в Firefox или IE, поэтому нужно внимательно проследить и понять, что стиль может быть серией хаков для исправления страницы за страницей. Я бы сказал, что это мои самые противные, которые иногда просто не фиксируются, поскольку они не считаются важными.
ПУТЬ назад в дни, утечки памяти. К счастью, в наши дни есть много инструментов для их поиска.
Проблемы с памятью, особенно в старых системах. У нас есть некоторое унаследованное 16-битное программное обеспечение C, которое должно оставаться 16-бит в настоящее время. Блоки памяти 64K - это королевская боль для работы, и мы постоянно добавляем статику или логику кода, которая подталкивает нас к пределам группы 64K.
Чтобы ухудшить ситуацию, ошибки памяти обычно не приводят к сбою программы, но вызывают определенные функции для спорадического разрыва (и не всегда одни и те же функции). Отладка не является опцией - отладчик не имеет одинаковых ограничений памяти, поэтому программы всегда работают нормально в режиме отладки... плюс мы не можем добавлять встроенные инструкции printf для тестирования, так как это еще больше повышает производительность памяти.
В результате мы иногда можем потратить DAYS, пытаясь найти один блок кода для перезаписи, или часы, перемещающие статические символы в файлы. К счастью, система медленно перемещается в автономном режиме.
Многопоточность, утечки памяти, все, что требует обширных макетов, взаимодействующих с сторонним программным обеспечением.