Re: Самый интересный баг, с которым вы возились
От: Maxion  
Дата: 23.09.13 10:50
Оценка: 2 (1)
Опишу три случая, которые запомнились на всю жизнь и с которыми пришлось достаточно долго провозиться.

Случай 1. Писал я как-то программу под ДОС на встроенном компьютере с 486 процессором – он использовался в одном устройстве и достаточно активно работал с различного рода «железом». Одной из задач у него была ретрансляция команд по RS232 с между двух портов (с одного устройства на другое), при этом некоторые из команд обрабатывались самим компьютером, да и он мог генерить «высоко приоритетные команды». В общем были там очереди с приоритетами на портах, а сами обработчики прерываний RS были написаны на ассемблере (остальная программа была на Borland C++ 3.1). Работал я в паре с другим разработчиком, который проектировал и программировал все остальной «железо». Итак, вечер перед отправкой «изделия» заказчику – у нас все отлажено и более-менее работает, а мы возимся с какой-то мелочевкой, в общем «допалировываем». И вдруг после исправления чего-то в коде Си перестает работать передача команд... Полностью. При этом исправленный кусок к передачи данных ни каким образом не относился. Просматриваю файлы – все нормально – никаких «подозрительных» мест не видно. Восстановление изменененого кода к прежнему состоянию — ничего не дает – передача команд не работает. Восстановление предыдущего ПО для «железа» (оно правилось параллельно) — так же не помогает. А со старой версией программы – все работает. В общем провозились мы с этой проблемой где-то час – два, пока я не сравнил построчно все файлы проекта, и не обнаружил, что в какой-то момент в обработчике прерывания RS исчезла одна строчка с ассемлерной командой – видимо при переключении окон в борланде я ее случайно удалил какой-то комбинацией клавиш... С одной стороны сейчас это звучит смешно – найти такую проблему пара минут, но тогда пришлось серьезно понервничать и выучить, что изменения могут быть не только в том коде, корый правишь, а и в любом другом месте проекта, даже который и «не трогал».

Случай 2. Случился с одним моим коллегой, но я принимал горячее участие в поиске «бага». Писал он программу для микроконтроллера на Си. И все было нормально, но вдруг одна функция перестала модифицировать одну переменную. Все остальное она делала как нужно, а вот одну переменную наотрез отказывалась модифицировать. Как мы это раскапывали – это отдельная история (отладчиком воспользоваться было нельзя и приходилось выводить промежуточные значения на спец. индикатор, ну и «дергать» ноги микроконтроллера для просмотра на осцилографе), но в результате выяснилось следующее: внутри одной функции, достаточно сложной, одна глобальная переменная должна была инкрементироваться, а она оставалась неизменной. При этом постепенно стала проявляться интересная картина – эта переменная внутри функции все-таки изменялась, но при выходе из функции она вдруг принимала исходное значение. Чего только не было испробовано и каких только предположений не было высказано – вплоть до ошибок в компиляторе. Но все оказалось намного банальнее – указанная глобальная переменная передавалась внутрь функции в качестве параметра (т.к. программист начитался умных книг и знал, что «использованиеглобальных переменных – зло» ), а внутри функции этот параметр был объявлен точно таким же именем, как и глобальная переменная... Из-за этого при беглом просмотре кода создавалось впечатление, что меняется глобальная переменная. Тем более, что она изменялась в конце достаочно длинной функции и именно туда было сосредоточено все внимание.

Случай 3. Самый «крышесносный» и интересный в моей жизни. Устанавливали мы как-то наше «изделие» у заказчика на заводе и адаптировали наш софт для интеграции его с роботами заказчика. Адаптация шла в основном в программе микроконтроллера нашего изделия. И вот в какой-то момент, добавив простейшее действие, что-то типа a += b + 100; мы обнаружили, что наше «изделие» перестало адекватно реагировать на команды робота. При этом частично реагировало нормально, а частично «сошло с ума» — мы даже описать это не смогли бы, настолько реакция оказалась «чудной». Убрали строчку – все нормально. Добавили – фигня. Изменили строчку c =b + 100; a += c; — ерунда, но по другому. Разнесли строчки – одну чуть выше по коду, другую чуть ниже – с роботом все восстановилось. Пожали плечами и вздохнули с облегчением – сдадим сегодня «изделие» заказчику. Вдруг обнаружили – «отвалилось» запоминание параметров во флэш-памяти. В общем не буду утомлять, но бились мы с этим несколько часов, пока не нашли какую-то комбинацию, когда все заработало (на самом деле там пришлось добавлять не одну строчку и подобная фигня была, можно сказать, практически с каждой строчкой). Но «изделие» сдали (и оно до сих пор там работает), а сами с недоумением поехали домой. Дома же, когда начали разбираться, то обнаружили следующее – после «заливки» программы в микроконтроллер в ней «портился» один байт. Изначально наш код по объему был чуть менее 64k, а во время доработок у заказчика перевалил через эту границу. Загрузчик же программы (утилита третьей фирмы) имел баг и в микроконтроллер на записывал последний байт в 64k блоке, вернее обнулял его.

Были еще случаи и с переполнением секундных счетчиков в 16 бит, и, как результат, снятия сигнала готовности на одну секунду раз в 18 минут (65536 / 3600). И поиск ошибки в программах системы, из-за чего длина участка материала, обрабатываемого нашим «изделиием» в некоторых случаях оказывалась меньше, чем заданное –причина оказалась в брызгах металла, которые постепенно нарастали в определенных местах на установке заказчика и создавали физическое препятствие . И поиск причин сбоев на конвейере, возникающих у заказчиков раз в неделю (причина оказалась в отсутствии блокировки прерываний при изменении пары переменных, которые всегда должны изменяться одновременно). Но это была «обычная» работа, которая не произвела очень сильного впечатления...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.