498 Часть III: Управление проектами и группами
ма останавливается. При следующем запуске функция, выполняющая всю
эту работу, должна снова присвоить счетчику строк значение 1.
Не инициализирован указатель
В переменных-указателях хранятся адреса памяти. Такая переменная
может, например, указывать начало определенной строки. Значение указа-
теля может меняться: например, вначале он содержит адрес первого сим-
вола строки, затем второго, третьего и т.д. Если указатель неправильно
инициализировать или забыть инициализировать вообще, он может содер-
жать неверный адрес. Если программа отображает фрагмент строки, "му-
сор" или не те элементы массива, скорее всего, ошибка связана с
использованием указателей.
Не очищена строка
В строковых переменных хранятся последовательности символов. Если
значением числовой переменной может быть 5, то значением строковой —
Привет, меня зовут Сергей. Строковые переменные могут отличаться по
длине. Переменной, в которой хранилась строка Привет, меня зовут Сер-
гей можно присвоить более короткую строку Пока. Присваивание может
работать по-разному (это зависит от компилятора и выбранного способа).
Если программист не допишет в конец новой строки пробелы, в результа-
те может получиться Покает, меня зовут Сергей.
Не инициализированы регистры
Регистрами называются специальные области памяти объемом в не-
сколько байтов, обычно находящиеся внутри центрального процессора.
Хранящимися в них данными компьютер манипулирует гораздо быстрее,
чем теми, которые записаны в обычной оперативной памяти. Поэтому
программисты часто пользуются регистрами для временного хранения дан-
ных. Они копируют несколько переменных в регистры, работают с ними,
а затем копируют их значения обратно в память. После этого бывает не-
обходимо восстановить исходные значения регистров, о чем часто забыва-
ют. Забывают также загрузить данные в один или несколько регистров.
Не сброшен флаг
Флаги — это переменные, значения которых являются сигналами об
определенных условиях. Флаг может быть установлен (истинен, включен,
равен 1) или сброшен (очищен, ложен, выключен, равен 0 или -1). В нор-
мальном состоянии флаг сброшен. Если одна часть программы хочет сооб-
щить другой о наступлении определенного события — о сбое,
инициализации переменной, ее переполнении, о том, что пользователь
нажал на клавишу, и т.п., тогда она устанавливает флаг этого события.
Приложение: Распространенные программные ошибки 499
Состояние флага всегда должно соответствовать условию, с которым он
связан. Например, подпрограмма может сбрасывать свой флаг при вызове
и устанавливать при выходе. Таким образом, установленный флаг будет
означать, что выполнение процедуры завершено нормально. Разумеется,
никакая другая процедура этим флагом пользоваться не должна. Некоторые
программы устанавливают и сбрасывают одни и те же флаги во многих
местах кода, так что трудно сказать, достоверны их значения или нет.
Данные должны были инициализироваться в другом
месте
Функция может инициализировать не все свои данные. Например,
переменные, которые она использует совместно с какой-нибудь другой
функцией, могут инициализироваться обеими. Предположим, что несколь-
ко функций из одного и того же меню используют несколько переменных,
инициализируемых программой при отображении этого меню. Если другого
способа вызвать эти функции нет, тогда все в порядке. Но что, если одна
из этих функций присутствует и в другом меню либо вызывается из блока
обработки ошибки в другой функции или еще откуда-нибудь?
Не выполнена повторная инициализация
Программист может забыть удостовериться, что при повторном вызове
функции в ее переменных содержатся правильные значения. Если, напри-
\ мер, переменная сохраняет свое значение от вызова к вызову и при ее
создании компилятор автоматически присваивает ей 0, программисту это-
го делать не нужно. Но только при первом вызове. Когда функция вызва-
на второй раз, в переменной, скорее всего, уже не нулевое значение.
Ожидает ли программист, что в ней всегда О?
Имейте в виду, что инициализация не всегда выполняется в самом
начале подпрограммы. При одном способе входа в нее или одном пути ее
выполнения данные могут быть инициализированы правильно, а при дру-
гом — нет.
Предположение, что данные не были
инициализированы
Иногда программа может инициализировать данные несколько раз под-
ряд. Такое повторение в общем не приносит вреда, за исключением потерь
I времени.
Путаница со статическими и динамическими
переменными
Динамические переменные создаются при входе в функцию и разруша-
ются при выходе из нее, в то время как статические создаются при самом