|
Программирование >> Аргументация конструирования
C;\WJNNT\Svslcm32\coramdn(lcotn !(Ввеянте следующее чиспо:1 Доведите следующее следующее [Введите спедукщее чиспо;-1 tExiting due to signal SlGFPfi [Diuision hv Zero at е1)=0Овв161д, x87 stdtiis=-O00B 9-. 1рах-ЙЙЙлЯ1Ь.э ebx-000001c5 ес =000а81Ьс1 pdx-0000Oa00 esi-O00000R4 cdi=0 !еЬр-000а81а8 esp-ea0aO17c jrogram=il:\GCC\III\CRRO[!, CX[Z cs- чеЬ-аиГ bdse-01c5O000 1 imit OEDbfFff ds: sel=01af base=Olc5M00 limi l=-O00bfTff ies: sei-Olflt base=eicbOMa limit=OU0brfff fs: sel=017f base-O0O0Cd20 limit-000effff sel=01bf base=090000O0 liiei t=O0]0ffff seb01af bflse-01c50O09 ] i mi 1 =flfl0bffff ripp stack: leeOaSlcc, .0Q0281CC] t:xct>pIn stack: !00028120..00026160] C.ill frame гасеЫзкк EIPs: 0X0000161d 0x00010746 sU:\(XC\ilD Рис. /7.7 . Выполнение первоначальной версии программы прерывается в результате ошибки и просто. Например, процессор мог потерять выполняемый код и продолжить выполнение машинных инструкций, не относящихся к программе (такое тоже иногда случается). Процессор мог использовать инструкцию деления как повод для генерации сообщения об ошибке, скрыв таким образом настоящий ее источник (программы с ошибками похожи на поезд, который сошел с рельсов: программа не остановится, пока не произойдет что-то действительно важное). О таких программах иногда говорят, что они стартовали в космос . Ну, а поскольку к ним прикрепили отдельный ярлык, значит, они встречаются довольно часто. Следующим шагом будет запуск программы из среды разработчика, поскольку иногда среды разработчика, например Visual C + + или GNU C + + , могут помочь в поиске ошибки. Далее приведен пример с использованием GNU C + + (работа в Visual C + + очень похожа на описанную ниже). Откройте программу в редакторе rhide, соберите и запустите ее, нажав клавиши <Ctrl+F9>. Введите 1, 2 и 3, а затем -1, и программа снова аварийно завершится. Для устранения ошибки сначала необходимо найти, какой именно фрагмент кода ее вызывает. Зная расположение ошибки, вы сможете воспроизвести ее во время отладки, а Также будете знать, когда ошибка уже исправлена. После запуска программы и возникновения ошибки rliide выдает окно, содержащее сообщение Program exiting code 255(0xf0 ( Программа завершилась с кодом выхода 255(0xfl) ), как показано на рис. 11.2. Я многого не знаю, но мне точно известно, что код нормального завершения нашей программы - 0. Невооруженным глазом видно, что этот код завершения не равен нулю, а значит, что-то пошло не так. Хотя я и не знаю, что именно означает код выхода Oxflf. Щелкните на кнопка ОК, и rhide кроме окна редактирования программы откроет еще два окна. 1; ROpm РЮОмге Next : F10 Шх1 nibM Qult : Рис 11.2. Код выхода Oxff означает, что программа завершилась аварийно Вы можете не видеть ксх трех окон одновременно, поскольку одно из них может быть скрыто другими. Чтобы переключиться в нужное окно, используйте клавишу <F6>. В третьем окне находится сообщение об ошибке, которое было создано во время запуска программы, но мы обратимся ко второму окну, показанному на рис. 11.3. , Т Kil Кип ПпипПр nebu iprt Ontion.s :HindoH5-HeiinKiS??; .=.iur. - - h:;/gcc/ii i/brror cpp trrorrrogram - эта программа усредаяла бы . рад жсел, если бы не.содержала . / / одну невьшошФмую опмбку Hinclucle <stdio-h> Hiiiclude. <ios<reaBi.h> lilt mainCint argc, char-pszfirgst] I cout а ограмма содержа оииВкиТЧп ; пользоватеж; fiocne чего вь int nSuH; сел, пока Ж tnter JUMP to source offi & Next тл-. не Henu ЯИ-Х Quit Рис. 11.3. Редактор 1с1способен вычислить, в какой части программы возниклаошибка Сообщение all fram back ( Отслеживание кадров вызовов ) звучит так же, как сообщение о шпионском радиоперехвате. Система выполняет просмотр адресов всех функций, вызванных программой, начиная с самой первой. В данном случае редн ошибка находится в main {}, которая б]ла вызвана функцией с названием crtlstartup (крайне содержательно, не правда ли?). Итак, ошибка возникла в строке 28 исходного файл тодгат. срр. Это уже теплее... Обратимся к строке 28 исходного файла: cout \nAverage is : строка 2 6 < nNuir.s строка 27 << \п ; строка 2 8 Думаю, никто из читателей не видит в строке 28 операции деления. Я тоже не вижу. Дело в том, что при компиляции C + рает все выражения до точки с запятой в одну строку, т.е. строки 26, 27 и 28 являются частями одной строки. Таким образом, все команды в строках 26-28 будут рассматриваться компилятором как одна 28-я строка. Теперь вы знаете, что ошибка возникла в результате деления в строке 27. Таким образом, можно заключить, что в момент деления переменная nNums была равна нулю. Эта переменная должна содержать количество введенных чисел. Просмотрев программу, можно увидеть, что была инициализирована нулем, но после этого ее значение не увеличивалось. Переменная должна была увеличиваться во вре- мя выполнения оператора for, так что для правильной работы программы нужно изменить строку, содержащую оператор for, следующим образом: for (inr nNums = 0; ;пЫишз + -) Впе жучка № 2 Теперь, когда найдена и исправлена ошибка № I, можно запустить программу, введя числа, заставившие ее в прошлый раз аварийно завершиться. На этот раз сообщение об ошибке не появится и программа вернет нулевой код выхода, но будет работать не так, как ожидалось. Вместо так горячо ожидаемой двойки будет выведено какое-то нелепое число. Эт оамма содержит ошибки! Введите е число: 1 Введите гледующее число: 2 Введите следующее число: 3 Введите :;ледующее -число: -1 Среднее равно: 229523 Ка++ находит ошибку в исходном коде Сообщение об ошибке, полученное во время запуска программы из MS DOS или Windows, было не очень информативным (особенно по сравнению с Visual C++ S или rhidG, которые смогли указать, где именно возникла ошибка). Как же среды разработки находят источник ошибки? Компилятор C++ поддерживает два режима построения программ. По умолчанию С + + строит программу в так называемом отладочном режиме. При этом компилятор добавляет в машинный код информацию о том, к какой строке исходного кода относится та или иная машинная инструкция, и тогда при запуске программы можно узнать, что, например, строка 200 машинного кода отвечает строке 16 исходной программы. При возникновении ошибки деления на ноль C++ по номеру строки машинного кода отслеживает, в каком месте исходной программы находилась ошибка. Такая отладочная информация занимает довольно много места. Поэтому при подготовке окончательной версии программы следует указать компилятору, что генерация исполняемого кода должна проводиться без отладочной информации.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |