Два друга по разному ищут ошибки в программах кирилл написав программу сразу запускает ее

Обновлено: 07.07.2024

Попытаюсь изложить тут свои соображения о том, как бороться с ошибками. Это всего лишь мои мысли, и не настаиваю что они совсем уж правильные. Возможно, я где-то у кого-то что-то слямзил на этот счет, но, честное слово сделал, это подсознательно и не надо меня обвинять в плагиате (по крайней мере, осознанном). Достаточно просто указать где, у кого и что (исправлюсь :) ).

Сразу хочется сказать, что есть такие не хорошие «плавающие» ошибки (они то есть, то их нет, при видимых одинаковых условиях). Печально, когда на них нарываешься и бороться с ними очень сложно – тут нужен имеющийся опыт, интуиция и бубен. Но и то, эта ошибка не берется из ни откуда, и у нее есть своя причина, только до причины этой очень сложно докопаться.

И еще, очень важно: прежде чем что-то исправлять в базе (программе) всегда делайте копию. Не важно, в каком состоянии сейчас база – копия должна быть всегда перед любым изменением (Не поверите, но ситуацию всегда можно ухудшить).

1. А был ли мальчик?

Первое о чем нужно подумать, если говорят что есть ошибка, а есть ли она? Не нужно сразу открывать конфигуратор (исходный код программы) и анализировать запрос. Нужно попросить пользователя показать эту ошибку. Если, по некой причине, показать он ее не может – досконально опросить в какой момент возникает ошибка, и попытаться ее воспроизвести (предположим, на тестовой базе).

В общем, главное любым способом увидеть эту ошибку своими глазами, или свято поверить, что она есть.

2. Разделяй и властвуй

Ошибка есть (увидели, убедились, поверили). Она стабильная (повторяется из раза в раз). Теперь мы пытаемся ее «упростить». В разных ситуациях делаем по разному, но суть одна – уменьшить пространство поиска.

2.1 К примеру оборотно-сальдовая ведомость за год показывает неправильные цифры. Начинаем уменьшать период, к примеру, по методу дихотомии золотого сечения (режем пополам и смотрим есть ли ошибка). Берем первое полугодие и смотрим, есть в нем ошибка. Если нет, значит ошибка во втором полугодии (лучше проверить это). Потом второе полугодие делим на кварталы и т.д. и т.п. – старый проверенный способ.

2.2 Другой пример при обмене данными через WEB-сервер в конечную программу попадают неправильные данные. Тут режем по алгоритму:

  1. Запрос формируется в исходной базе
  2. Данные перегоняются по сетке в базу приемник
  3. База приемник получает данные и записывает их
  1. Смотрим в исходной базе, что выдает запрос. Для этого пользуемся отладчиком, консолью запросов, всем чем угодно, но именно в этой базе (что бы отсечь все другие этапы)
  2. Смотрим, как работает web-сервис (сравниваем что ему отдает запрос, как он эти данные преобразовывает, и получаем ли мы на входе в базу приемник то самое что отправилось из базы источника)
  3. Смотрим, как база приемник разбирает полученные данные. Для этого можно создать (сохранить) отдельный файл обмена, и подавать ее раз за разом в качестве исходных данных (тем самым мы опять таки исключаем два других этапа)

2.4 Если неправильно работает процедура документа (например проведение), тот тут используем отладчик. Все знают, что к любой конфигурации можно подключится отладчиком. Для этого

  • пользовательском режиме у конфигурации должна стоять опция «Параметры / Системные / Отладка разрешена».
  • запустить ту же самую конфигурацию в режиме конфигурирования и через «Отладка / Подключение» подключится к нужному пользовательскому сеансу.

Подключившись отладчиком, используем точки останова, трассировку, табло, стек вызова, «вычисление выражения» и т.д. и т.п., опять таки «режа» код на возможно мелкие кусочки, содержащие ошибку. Мне кажется, найти ошибку при помощи отладчика гораздо проще, чем теоретически анализируя код.

Не думаю, что нужно расписывать все возможности отладчика, поскольку в руководствах пользователя и прочей «официальной литературе» это сделано куда как лучше :)

В общем, главное локализовать ошибку (упростить ее).

3. Спасение утопающих

  • в синтакс-помощнике (среди описания операторов)
  • в пресловутых «желтых книгах»
  • в других конфигурациях (по принципу «как там так и у меня должно быть»)
  • в интернете.
  1. Чем дольше вы ищите, тем лучше запомните этот случай и лучше научитесь работать с источниками.
  2. В процессе поиска вы найдете что-то другое, не относящееся к этому вопросу, но тоже очень полезное.

Вопрос должен быть кратким (читаемым) и конкретным, а иначе получится просто заспаменную тему с ехидными замечаниями «о жизни».

В общем, прежде чем обратиться за помощью, до последнего старайтесь решить ошибку сами.

А тем кто отвечает очень хочется напомнить фразу «Мы все одинаково невежественные, но в разных областях» (Феликс Райчак не помню автора). Если спрашивают – это не значит что тот кто спрашивает глупее, он может быть просто менее опытный в этом вопросе. Хорошо что он пытается учиться, и мерзко его за это гнобить. Если не можешь ответить по теме (более чем пустой фразой «гугл найдет все») – лучше промолчать.

Заключение

Много букв получилось (расчувствовался :) ). Не оригинально, достаточно банально и очевидно. Даже, немного стыдно публиковать :) Но как ни странно очень часто сталкиваешься с тем, что эти всем известные истины люди упорно игнорируют.

Или я в чем-то ошибаюсь?

ЗЫ. Если текст бесполезный – можно снять публикацию. Во вложении, тот же текст но виде файла WORD (на всякий случай)

ЗЫЗЫ. Исправил обнаруженые ошибки

Хватит гуглить ответы на профессиональные вопросы! Доверьте их экспертам «Клерка». Завалите лучших экспертов своими вопросами, они это любят!

Ответ покажется вам парадоксальным. Лучше ее вообще не искать. Вижу озадаченные лица. Кто-то с возмущением вновь перечитывает эти строки и ставит под сомнение компетентность автора. Но я повторю: лучше ее не искать. Конечно, самое правильное - ее не делать. Но возможно ли такое? Это в реальном мире мы считаем, что можем безошибочно прожить день. На самом деле в наших действиях - масса неувязок, которых мы просто не замечаем. А компьютер сразу выявляет их и представляет нам в развернутом виде.
Итак, программист ввел несколько новых операторов, после чего работавшая до того программа полностью перестала функционировать. Хорошо, если нововведений мало. Тогда в них легче разобраться. Программист зорким взглядом определил, где он ошибся, и быстро исправил. Программа не заработала. Тогда он стал внимательно изучать каждый новый символ. Наконец, радостно хлопнув себя по лбу и воскликнув: - Как все просто! – Он сделал еще одну корректуру и пустил модуль на выполнение. Но что такое? Программа аварийно завершилась!
Не в силах больше выносить такое издевательство от своего детища, программист
убрал все новшества и облегченно вздохнул. Он вернулся к прежнему варианту.
Сейчас он убедится, что программа работает и начнет вносить корректуру построчно. Но вот беда! Убедиться не удается. Программа не идет, как будто новые операторы не убраны! Но ведь он их убрал! Их нет!
К сожалению, такие ситуации случаются нередко. Лично со мной они были.
Выход из них, надо признаться, тяжеловат. Не знаешь, где и что искать и за что хвататься. Порой на поиск причины уходят дни. А так хотелось завершить работу еще сегодня!

В этом случае, имеет смысл, вернуться к версии до изменений, причем не так, как сделал вышеописанный программист, а взять текст из копии. Это позволит не ломать голову над загадочной проблемой и думать о более существенных вещах.
Рассмотрим все сначала. Программа начата, отладочная среда существует. Предлагаю идти маленькими шажками, внося обозримые изменения и сразу подвергая их отладке. По завершению каждого, пусть небольшого этапа, имеет смысл делать копию. В таком поступательном режиме можно долгое время избегать серьезных ошибок. Но вот, наконец, Вам “удалось” ее сделать. Если чувствуете, что увязаете в поиске, то рекомендую вернуться к состоянию до ошибочной корректуры. Вот в чем смысл фразы, с которой я начинал повествование. Ломка головы над вылавливанием ошибки не всегда полезна. Поломать голову еще придется.
Описал я, кстати, очень хороший вариант ошибки. Вы опять удивлены? Не надо. Когда программа перестает работать сразу – это моментальный диагноз Ваших действий. Вы вынуждены что-то предпринимать, чтобы выровнять ситуацию.
И, как правило, такого рода ошибки, как бы Вы с ними не помучались, найти все-таки легче, чем те, что не проявились сразу.
Бывают очень тонкие, очень коварные недочеты, которые проявятся, где-то, через год эксплуатации, а то и позже.

К примеру, Вы что-то накрутили с тысячными долями копейки или миллиметра.
Через 7 месяцев, когда уже и забыта данная работа, а на руках давно другая, к Вам прибегает бухгалтер с пытливо выпученными глазами и говорит, что у нее потерялись 132 тысячи. Аналогично можно представить, как заказчик расчета на прочность раздосадован тем, что длина детали у него получилась отрицательная.
Здесь уже к начальному безошибочному варианту не вернешься. Надо ликвидировать ляпсус и постараться не зацепить что-нибудь еще. Когда ошибка идет стабильно – это прекрасно. Ее гораздо легче выловить. Но, если она - то есть, то нет – это куда хуже. Такие ошибки иногда называют плавающими. Они обычно возникают из-за случайно заносимой информации в какое-то поле.

В старых операторных языках все поля были у нас под контролем. Их было можно и сравнительно легко отследить и также легко запортить. В новых, объектно-ориентированных – все сделано так, чтобы мы поменьше попадали на нижний уровень. Но умудриться напортачить, поверьте мне, можно и здесь.
Иногда причина неверной работы программы не в одной, а в двух накладывающихся ошибках. Выловить их гораздо сложнее. Они создают плавающий эффект. Программа “вылетает” то в одном, то в другом месте и, вообще, творит что-то невообразимое. Что ни делаешь, не можешь найти логики. В этих случаях полезно самому в текст программы внести что-то нелогичное.

Зачем? Дело в том, что Вам необходимо сдвинуться с мертвой точки любым способом, раскачать лодку так, чтобы она перевернулась. И тогда программа выдаст что-то более понятное для Вас, а Ваши бедные мозги вдруг станут на место.
Вот я слегка коснулся будоражащего воображение программиста понятия “ошибка”. Не претендую на то, что мои советы самые надежные и точные.
Просто я делюсь своим не совсем скромным опытом.

Требовалось написать программу, которая решает неравенство относительно x для любых ненулевых чисел a и b введенных с клавиатуры. Все числа считаются действительными. Программист торопился и написал программу неправильно.

PRINT "x > ",a," или x 0 THEN

write ('x > ', a, ' или x 0 then

Последовательно выполните три задания:

1) Приведите пример таких чисел а, b, х, при которых программа неверно решает поставленную задачу.

2) Укажите, какая часть программы является лишней.

3) Укажите, как нужно доработать программу, чтобы не было случаев ее неправильной работы. (Это можно сделать несколькими способами, поэтому можно указать любой способ доработки исходной программы).

1) a = −11, b = 1, x = 0.

Значение x может быть не указано. Значение а может быть любым отрицательным числом, значение b — любым положительным. Также допустим ответ, что программа работает неправильно при любых положительных b и отрицательных а.

не нужно вводить х с клавиатуры; верно: readln(a, b).

3) Возможная доработка:

write('х >', а, 'или х 0')

Для заданного положительного вещественного числа A необходимо найти минимальное целое число K, при котором выполняется неравенство Для решения этой задачи ученик написал такую программу.

DIM A, S AS DOUBLE

DIM K AS INTEGER

while s>=a do begin

using namespace std;

Последовательно выполните следующее.

1. Напишите, что выведет эта программа при вводе числа 1.4.

2. Сколько существует натуральных чисел А, при вводе которых программа выведет ответ 1?

3. Найдите в программе все ошибки (их может быть одна или несколько).

Решение использует запись программы на Паскале. Допускается использование программы на других языках.

1. При вводе числа 1.4 программа выведет число 0.

2. Программа не выведет ответ 1 ни при каком вводе, то есть ответ на задание: 0. Примечание для проверяющего. При вводе A > 1 тело цикла не будет выполнено ни разу и программа выведет ответ 0. При A ≤ 1 происходит зацикливание.

3. Программа содержит две ошибки.

1) Неверная инициализация. Переменные s и k должны иметь одинаковые начальные значения: либо обе равны нулю, либо обе равны единице.

2) Неверное условие цикла.

Возможные варианты исправления для языка Паскаль следующие. Первая ошибка содержится в одной (любой) из двух строк:

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

Для записи программ используется конечный набор символов, составляющих алфавит языка программирования. В отличие от привычных алфавитов (например, русского) алфавит языка программирования включает в себя, кроме букв, цифры, знаки препинания, знаки арифметических действий и некоторые другие дополнительные символы. Программа записывается в виде последовательности символов из алфавита своего языка программирования. Естественно, что не любой текст, составленный из символов алфавита, будет правильной программой. Как и в естественных языках, правильность построения программы из символов алфавита можно проверить, используя синтаксис языка программирования.

Синтаксис языка программирования — это набор правил, которые определяют способы построения правильных программ из символов алфавита. Зная синтаксис языка, можно построить алгоритм, который определяет, является ли данный текст правильной программой или нет. Этот алгоритм позволяет компьютеру проверять синтаксическую правильность вводимых в него программ.

Должна быть определена и семантика языка программирования. Семантика языка программирования — это набор правил, по которым исполнитель выполняет программы на этом языке. Пользуясь семантикой языка, можно однозначно определить результат выполнения программы с заданными входными данными.

При чтении программы необходимо сначала определить, к какому виду она относится. Условно программы можно разделить на два вида: простая программа без использования подпрограмм (кроме стандартных процедур ввода\вывода) и программа, использующая подпрограммы (подалгоритмы). Такая программа может включать в свою структуру как стандартные подпрограммы, так и подпрограммы, написанные пользователем.

Для чтения простой программы необходимо выяснить:

  • что является входными данными и как они вводятся в программу;
  • какие действия последовательно выполняются с помощью каждого функционального узла программы (операторов), т. е. рассмотреть пошаговое выполнение операторов, при этом обратить внимание на роль вспомогательных переменных, массивов и т.д.;
  • что является результаты работы программы;
  • каковы ограничения по работе алгоритма.

При чтении программы, использующей подпрограммы, необходимо сначала проанализировать, что и как выполняют подпрограммы, каковы их входные и выходные параметры. Затем в основной программе вызовы каждой из подпрограмм рассматривать уже как результат работы соответствующего подалгоритма.

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

Примеры чтения программ на языках Pascal, QBASIC

Примечание. В приведенных примерах программа приводится для двух языков программирования. В зависимости от того, какой язык программирования изучается, и следует рассматривать ее вариант записи и соответствующие пояснения.

Пример 1. Дана программа на двух языках программирования. Определить, какую задачу она решает.


Решение. Проанализируем тексты программы:

  1. формируется тело программы и описываются переменные;
  2. вводятся натуральные числа М и N, причем проверяется условие корректности ввода: числа должны быть положительные. Если введенные значения не удовлетворяют условию, то ввод повторяют, пока условие не будет выполнено;
  3. выбирается наименьшее значение из М и N, результат записывается в K;
  4. NOD присваивается значение 1;
  5. в цикле от двух до K генерируется число I;
  6. тело цикла — в условном операторе проверяется, является ли значение переменной I одновременно делителем М и N. Если условие выполняется, то текущее значение I сохраняется в переменной NOD; если условие не выполняется, NOD не изменит своего значения;
  7. после перебора всех значений I в NOD или запишется наибольший делитель двух чисел М и N, или останется значение 1;
  8. последний оператор программы служит для вывода результата работы программы — значения переменной NOD.

Переменные, используемые в программе:

N, М — исследуемые числа;

I — переменная цикла;

NOD — наибольший общий делитель;

К — наименьшее из М и N.

Ответ: данная программа позволяет определить для двух чисел М и N их наибольший общий делитель NOD.

Примечание. Эту же задачу можно решить, используя алгоритм Евклида.

Пример 2. Дана программа на двух языках программирования. Определить, какую задачу она решает.

Читайте также: