вопрос программистам, кодерам: как вы ищите ошибки?
если не лезть в высокую науку, можно условно разделить алгоритмы на <<арифметику>> (там где что то считаем) и <<бухгалтерию>> (там где как то реорганизуем данные). и, если в арифметике найти ошибку легко, то в бухгалтерии это сущий ад. особенно, если ошибка мелкая и пакостная. например, сегодня провозился 4 часа (SIC!) в поисках ошибки в банальнейшем коде, дефрагментирущем массив на каждой итерации счёта. дошёл до того, что просто выписал злосчастный кусок его на бумагу и вручную прошёлся по каждой ветке, пока не наткнулся на то, что ... в одном месте банально перепутаны местами операторы. если уж делаю такие ошибки, то дебилу ясно, что у меня какой то косяк со стилем программирования. как таких вещей избегать?
В NetBeans есть хорошая вещь (в яве) как окно выполнения, там в реальном времени возникнет тип ошибки и строка, на которой она возникла. Если код не обфусцирован, разумеется. Ну а потом уже логика и интуиция.
ну такие вещи я через gdb отлавливаю, а когда код 10000 раз отрабатывает правильно, а на 10001 записывает неверное значение и заметить это получается только из за нефизичного результата счёта.
Ошыбки бывают трёх типов: понятные, непонятные и порчя памяти.
Понятные ошибки, это когда тебе отладчик заботливо указывает на строчку, в которой произошел вылет. Непонятные, это когда отладчик не в силах ничего показать, только вопросики, а адрес, по которому произошел вылет обычно имеет каноничный вид 0x00000005.
Ну это понятное дело - где-то претоилса непроинициализированный указатель на функцию, переход по нему всегда даёт 4 байта от нулевого указателя, ну а дальше попытка чтения аргументов всегда заканчивается нехорошо. Отсюда и такой адрес. Найти такое достаточно легко, если вылет произошел сразу после последней модификации исходников и достаточно непросто, если к вылету привела целая цепочка случайных последовательностей. Обычные (по крайней мере для меня), методы выявления подобной пакости - это ассерты, брык-поинты и контрольные мессаги. Ну камрад Ксерокс еще наверняка упомянет _asm int 3;
основная задача - расставлять хитрые условия и проверки, постепенно сужая круг поисков. Обычное виндовое приложение работает в цикле.
Значит от начала и до конца цикла мы постепенно проходим с нашими инструментами локализуя, сначало грубо, а потом и более точно место вылета. Поскольку подобный подход чем-то напоминает бинарный алгоритм поиска, то и скорость нахождения бага обычно очень высока - не более 10 минут. В наиболее тяжелых случаях - 2-3 часа.
Порчя памяти, особенно нерегулярная есть самый настоящий ужос для разработчика, поскольку бывают случаи когда выявить истинную причину практически невозможно. Подлость тут кроется еще и в том, что приложение может нормально запускаться и работать, а падать при высвобождении памяти. Такое ни в коем случае нельзя оставлять "как есть" - кто знает как поведет себя подобная программа при длительной работе.
Надо ещё очень хорошо притереться к своему компилятору. А то ведь ежели не знаешь про "любовь" MinGW к функции FreeLibrary - можешь поседеть, а причину таинственных ошибок по неизвестным адресам и за двадцать лет не найти.
Добавлено 10-11-2012 в 22:06:
Цитата:
Дядя Миша писал: Ну камрад Ксерокс еще наверняка упомянет _asm int 3;
В волатиле правильно писать - __asm__ __volatile__( "int 3h"), ну по понятным причинам.
ну ёлки-палки. ну я, видимо, действительно идиот с дефектом мозга. сегодня 5(!) битых часов искал ошибку. оказалось, в одном месте, слегка не хватает точности. +нашёл одну старую ошибку, в одном месте в имени переменной было лишнее подчёркивание.
да я так и не понял отчего так. никаких оптимизаций не использовал.
используется одна и та же функция для проверки пересечения траектории частицы с границей. так вот, если трейсить коротким вектором -- \vec{r0}->\vec{r1}, (начальное положение частицы->конечное положение частицы), то этот \vec{r1} изредка почти лежит на границе и пересечение не детектируется, а если трейсить длинным вектором, из того же \vec{r1} до какой ни будь точки вне системы и по кол-ву пересечений определять вылетела частица или нет, то всё прекрасно отрабатывает. или я идиот или одно из двух. сделаю двойную проверку тогда, что б уж наверняка.