Всего на сайте:
183 тыс. 477 статей

Главная | Информатика

Невоспроизводимые ошибки  Просмотрен 178

 

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

Проверьте, что все переменные инициализированы. Может быть, вы просто используете случайное значение, оставшееся в повторно используемой ячейке памяти. При написании программ на С и C++ в этом чаще вcero виновны локальные переменные функций и выделяемая память.

Установите все переменные в заранее известное значение; напрмер, если стартовое значение генератора случайных чисел обычно вычисляется исходя из времени суток, то присвойте ему нулевое значение.

Если ошибка изменяет свое поведение или вообще исчезает при до­бавлении отладочного кода, то это может быть связано с выделением памяти: где-то вы пишете за пределы выделенной памяти, а добавление отладочного кода изменяет расположение данных в памяти, так что ошибка начинает проявляться по-другому. Большинство функций вы­вода, от printf до диалоговых окон, захватывают для себя память сами, еще больше "мутя воду".

Если место ошибки, казалось бы, находится далеко от любого места, в котором она могла бы появиться, значит, происходит запись за преде­лы доступной памяти, причем затирается значение, которое использует­ся лишь гораздо позже. Иногда случается проблема "висящих указате­лей", когда указатель на локальную переменную случайно передается за пределы функции, а затем используется. Возврат адреса локальной пе­ременной — лучший способ создания ошибки замедленного действия:

 

? char *msg(int n, char *s)

? {

? char buf[100];

?

? sprintf(buf, "error %d: %s\n", n, s);

? return but;

? }

 

К тому моменту, когда указатель, возвращаемый функцией msg, исполь­зуется, он уже не указывает на осмысленное место.

Память нужно выде­лять с помощью функции malloc, использовать массив, объявленный как static, или требовать предоставления памяти вызывающей программой.

Использование динамически выделяемого значения после того, как оно было освобождено, имеет подобные симптомы. Мы уже упоминали об этом во второй главе, когда написали функцию freeall. Вот этот код — неверен:

 

? for (р = listp; р != NULL; р = p->next)

? free(p);

 

После того как память была освобождена, она не должна использовать­ся, потому что ее содержимое могло измениться и нет гарантии, что p->next все еще указывает на правильное значение.

В некоторых реализациях malloc и free повторное освобождение участка памяти портит внутренние структуры, но не вызывает никаких проблем до тех пор, пока гораздо позже какая-нибудь другая операция выделения памяти не поскользнется на испорченном участке памяти.

Некоторые реализации динамического выделения памяти имеют отладочные возможности для проверки корректности области динамической памяти при каждом вызове. Включите такую отладку, если вы столкнулись с недетерминированной ошибкой. В крайнем случае вы можете написать собственную реализацию динамической памяти, которая проверяет каждую операцию или просто заносит эти операции в журнал для дальнейшего изучения. Если ситуация удручает, достаточно написать простую, не очень скоростную реализацию. Есть также великолепные коммерческие продукты, проверяющие работу с памятью и отлавливающие ошибки и утечки; если у вас таких нет, собственная версия malloc и f гее может в какой-то мере их заменить.

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

Предыдущая статья:Последняя надежда Следующая статья:Средства отладки
page speed (0.0318 sec, direct)