Ошибки при вводе информации в компьютерную программу
Большинство программ, имеющих какой-либо пользовательский интерфейс, должны обрабатывать вводимые пользователем данные. В программах, которые мы писали, мы использовали std::cin , чтобы попросить пользователя ввести текст. Поскольку ввод текста имеет произвольную форму (пользователь может вводить что угодно), пользователю очень легко ввести данные, которые не ожидаются.
При написании программ вы всегда должны учитывать, как пользователи (непреднамеренно или наоборот) будут использовать ваши программы некорректно. Хорошо написанная программа будет предвидеть, как пользователи будут использовать ее неправильно, и либо аккуратно обработает эти случаи, либо вообще предотвратит их появление (если это возможно). Программа, которая хорошо обрабатывает случаи ошибок, называется надежной.
В этом уроке мы подробно рассмотрим способы, которыми пользователь может вводить недопустимые текстовые данные через std::cin , и покажем вам несколько разных способов обработки таких случаев.
std::cin , буферы и извлечение
Чтобы обсудить, как std::cin и operator>> могут давать сбой, сначала полезно немного узнать, как они работают.
Когда мы используем operator>> для получения пользовательского ввода и помещения его в переменную, это называется «извлечением». Соответственно, в этом контексте оператор >> называется оператором извлечения.
Когда пользователь вводит данные в ответ на операцию извлечения, эти данные помещаются в буфер внутри std::cin . Буфер (также называемый буфером данных) – это просто часть памяти, отведенная для временного хранения данных, пока они перемещаются из одного места в другое. В этом случае буфер используется для хранения пользовательских входных данных, пока они ожидают извлечения в переменные.
При использовании оператора извлечения происходит следующая процедура:
- Если во входном буфере уже есть данные, то для извлечения используются они.
- Если входной буфер не содержит данных, пользователя просят ввести данные для извлечения (так бывает в большинстве случаев). Когда пользователь нажимает Enter , во входной буфер помещается символ '\n' .
- operator>> извлекает столько данных из входного буфера, сколько может, в переменную (игнорируя любые начальные пробельные символы, такие как пробелы, табуляции или '\n' ).
- Любые данные, которые не могут быть извлечены, остаются во входном буфере для следующего извлечения.
Извлечение завершается успешно, если из входного буфера извлечен хотя бы один символ. Любые неизвлеченные входные данные остаются во входном буфере для дальнейшего извлечения. Например:
Если пользователь вводит "5a" , 5 будет извлечено, преобразовано в целое число и присвоено переменной x . А "a\n" останется во входном потоке для следующего извлечения.
Извлечение не выполняется, если входные данные не соответствуют типу переменной, в которую они извлекаются. Например:
Если бы пользователь ввел 'b' , извлечение не удалось бы, потому что 'b' не может быть извлечено в переменную типа int .
Проверка ввода
Процесс проверки того, соответствуют ли пользовательские входные данные тому, что ожидает программа, называется проверкой ввода.
Есть три основных способа проверки ввода:
- встроенный (по мере печати пользователя):
- прежде всего, не позволить пользователю вводить недопустимые данные;
- позволить пользователю ввести в строку всё, что он хочет, затем проверить правильность строки и, если она корректна, преобразовать строку в окончательный формат переменной;
- позволить пользователю вводить всё, что он хочет, позволить std::cin и operator>> попытаться извлечь данные и обработать случаи ошибок.
Некоторые графические пользовательские интерфейсы и расширенные текстовые интерфейсы позволяют проверять входные данные, когда пользователь их вводит (символ за символом). В общем случае, программист предоставляет функцию проверки, которая принимает входные данные, введенные пользователем, и возвращает true , если входные данные корректны, и false в противном случае. Эта функция вызывается каждый раз, когда пользователь нажимает клавишу. Если функция проверки возвращает истину, клавиша, которую только что нажал пользователь, принимается. Если функция проверки возвращает false , введенный пользователем символ отбрасывается (и не отображается на экране). Используя этот метод, вы можете гарантировать, что любые входные данные, вводимые пользователем, гарантированно будут корректными, потому что любые недопустимые нажатия клавиш обнаруживаются и немедленно отбрасываются. Но, к сожалению, std::cin не поддерживает этот стиль проверки.
Поскольку строки не имеют никаких ограничений на ввод символов, извлечение гарантированно завершится успешно (хотя помните, что std::cin прекращает извлечение на первом неведущем пробельном символе). После того, как строка введена, программа может проанализировать эту строку, чтобы узнать, корректна она или нет. Однако анализ строк и преобразование вводимых строк в другие типы (например, числа) может быть сложной задачей, поэтому это делается только в редких случаях.
Пример программы
Рассмотрим следующую программу-калькулятор, в которой нет обработки ошибок:
Эта простая программа просит пользователя ввести два числа и математический оператор.
Теперь подумайте, где неверный ввод пользователя может нарушить работу этой программы.
Сначала мы просим пользователя ввести несколько чисел. Что, если он введет что-то, отличающееся от числа (например, 'q' )? В этом случае извлечение не удастся.
Во-вторых, мы просим пользователя ввести один из четырех возможных символов. Что, если он введет символ, отличный от ожидаемых? Мы сможем извлечь входные данные, но пока не обрабатываем то, что происходит после.
В-третьих, что, если мы попросим пользователя ввести символ, а он введет строку типа "*q hello" . Хотя мы можем извлечь нужный нам символ '*' , в буфере останутся дополнительные входные данные, которые могут вызвать проблемы в будущем.
Типы недопустимых входных текстовых данных
Обычно мы можем разделить ошибки ввода текста на четыре типа:
- извлечение входных данных выполняется успешно, но входные данные не имеют смысла для программы (например, ввод 'k' в качестве математического оператора);
- извлечение входных данных выполняется успешно, но пользователь вводит дополнительные данные (например, вводя "*q hello" в качестве математического оператора);
- ошибка извлечения входных данных (например, попытка ввести 'q' при запросе ввода числа);
- извлечение входных данных выполнено успешно, но пользователь выходит за пределы значения числа.
Таким образом, чтобы сделать наши программы устойчивыми, всякий раз, когда мы запрашиваем у пользователя ввод, мы в идеале должны определить, может ли произойти каждый из вышеперечисленных возможных вариантов, и если да, написать код для обработки этих случаев.
Давайте разберемся в каждом из этих случаев и в том, как их обрабатывать с помощью std::cin .
Случай ошибки 1: извлечение успешно, но входные данные не имеют смысла
Это самый простой случай. Рассмотрим следующий вариант выполнения приведенной выше программы:
В этом случае мы попросили пользователя ввести один из четырех символов, но вместо этого он ввел 'k' . 'k' – допустимый символ, поэтому std::cin успешно извлекает его в переменную op , и она возвращается в main . Но наша программа не ожидала этого, поэтому она не обрабатывает этот случай правильно (и, таким образом, ничего не выводит).
Решение здесь простое: выполните проверку ввода. Обычно она состоит из 3 шагов:
- убедитесь, что пользовательский ввод соответствует вашим ожиданиям;
- если да, верните значение вызывающей функции;
- если нет, сообщите пользователю, что что-то пошло не так, и попросите его повторить попытку.
Вот обновленная функция getOperator() , которая выполняет проверку ввода.
Как видите, мы используем цикл while для бесконечного цикла до тех пор, пока пользователь не предоставит допустимые данные. Если он этого не делает, мы просим его повторить попытку, пока он не даст нам правильные данные, не закроет программу или не уничтожит свой компьютер.
Случай ошибки 2: извлечение успешно, но с посторонними входными данными
Рассмотрим следующий вариант выполнения приведенной выше программы:
Как думаете, что будет дальше?
Программа выводит правильный ответ, но форматирование испорчено. Давайте подробнее разберемся, почему.
Когда пользователь вводит "5*7" в качестве вводных данных, эти данные попадают в буфер. Затем оператор >> извлекает 5 в переменную x , оставляя в буфере "*7\n" . Затем программа напечатает "Enter one of the following: +, -, *, or /:" . Однако когда был вызван оператор извлечения, он видит символы "*7\n" , ожидающие извлечения в буфере, поэтому он использует их вместо того, чтобы запрашивать у пользователя дополнительные данные. Следовательно, он извлекает символ '*' , оставляя в буфере "7\n" .
После запроса пользователя ввести другое значение double , из буфера извлекается 7 без ожидания ввода пользователя. Поскольку у пользователя не было возможности ввести дополнительные данные и нажать Enter (добавляя символ новой строки), все запросы в выводе идут вместе в одной строке, даже если вывод правильный.
Хотя программа работает, выполнение запутано. Было бы лучше, если бы любые введенные посторонние символы просто игнорировались. К счастью, символы игнорировать легко:
Этот вызов удалит до 100 символов, но если пользователь ввел более 100 символов, мы снова получим беспорядочный вывод. Чтобы игнорировать все символы до следующего символа '\n' , мы можем передать std::numeric_limits::max() в std::cin.ignore() . std::numeric_limits::max() возвращает наибольшее значение, которое может быть сохранено в переменной типа std::streamsize . Передача этого значения в std::cin.ignore() приводит к отключению проверки счетчика.
Чтобы игнорировать всё, вплоть до следующего символа '\n' , мы вызываем
Поскольку эта строка довольно длинная для того, что она делает, будет удобнее обернуть ее в функцию, которую можно вызвать вместо std::cin.ignore() .
Поскольку последний введенный пользователем символ должен быть '\n' , мы можем указать std::cin игнорировать символы в буфере, пока не найдет символ новой строки (который также будет удален).
Давайте обновим нашу функцию getDouble() , чтобы игнорировать любой посторонний ввод:
Теперь наша программа будет работать, как ожидалось, даже если мы введем "5*7" при первом запросе ввода – 5 будет извлечено, а остальные символы из входного буфера будут удалены. Поскольку входной буфер теперь пуст, при следующем выполнении операции извлечения данные у пользователя будут запрашиваться правильно!
Случай ошибки 3: сбой при извлечении
Теперь рассмотрим следующий вариант выполнения нашей программы калькулятора:
Неудивительно, что программа работает не так, как ожидалось, но интересно, как она дает сбой:
и программа внезапно завершается.
Это очень похоже на случай ввода посторонних символов, но немного отличается. Давайте посмотрим подробнее.
Когда пользователь вводит 'a' , этот символ помещается в буфер. Затем оператор >> пытается извлечь 'a' в переменную x , которая имеет тип double . Поскольку 'a' нельзя преобразовать в double , оператор >> не может выполнить извлечение. В этот момент происходят две вещи: 'a' остается в буфере, а std::cin переходит в «режим отказа».
Находясь в «режиме отказа», будущие запросы на извлечение входных данных будут автоматически завершаться ошибкой. Таким образом, в нашей программе калькулятора вывод запросов всё еще печатается, но любые запросы на дальнейшее извлечение игнорируются. Программа просто выполняется до конца, а затем завершается (без вывода результата потому, что мы не прочитали допустимую математическую операцию).
Давайте, интегрируем это в нашу функцию getDouble() :
Примечание. До C++11 неудачное извлечение не приводило к изменению извлекаемой переменной. Это означает, что если переменная была неинициализирована, она останется неинициализированной в случае неудачного извлечения. Однако, начиная с C++11, неудачное извлечение из-за недопустимого ввода приведет к тому, что переменная будет инициализирована нулем. Инициализация нулем означает, что для переменной установлено значение 0, 0.0, "" или любое другое значение, в которое 0 преобразуется для этого типа.
Случай ошибки 4: извлечение успешно, но пользователь выходит за пределы значения числа
Рассмотрим следующий простой пример:
Что произойдет, если пользователь введет слишком большое число (например, 40000)?
В приведенном выше случае std::cin немедленно переходит в «режим отказа», но также присваивает переменной ближайшее значение в диапазоне. Следовательно, x остается с присвоенным значением 32767. Дополнительные входные данные пропускаются, оставляя y с инициализированным значением 0. Мы можем обрабатывать этот вид ошибки так же, как и неудачное извлечение.
Примечание. До C++11 неудачное извлечение не приводило к изменению извлекаемой переменной. Это означает, что если переменная была неинициализирована, в случае неудачного извлечения она останется неинициализированной. Однако, начиная с C++11, неудачное извлечение вне диапазона приведет к тому, что переменной будет присвоено ближайшее значение в диапазоне.
Собираем всё вместе
Вот наш пример калькулятора с полной проверкой ошибок:
Заключение
При написании программы подумайте о том, как пользователи будут неправильно использовать вашу программу, особенно при вводе текста. Для каждой точки ввода текста учтите:
- Могло ли извлечение закончиться неудачей?
- Может ли пользователь ввести больше, чем ожидалось?
- Может ли пользователь ввести бессмысленные входные данные?
- Может ли пользователь переполнить входные данные?
Вы можете использовать операторы if и булеву логику, чтобы проверить, являются ли входные данные ожидаемыми и осмысленными.
Следующий код очистит любые посторонние входные данные:
Следующий код будет проверять и исправлять неудачные извлечения или переполнение:
Наконец, используйте циклы, чтобы попросить пользователя повторно ввести данные, если исходные входные данные были недопустимыми.
Примечание автора
Проверка ввода важна и полезна, но она также делает примеры более сложными и трудными для понимания. Соответственно, на будущих уроках мы, как правило, не будем проводить никакой проверки вводимых данных, если они не имеют отношения к чему-то, чему мы пытаемся научить.
Многие компании считают, что работают и принимают решения на основе данных, но часто это не так. Ведь для того чтобы управление велось на основе данных, их, эти самые данные, недостаточно только собрать и свести в статистику.Намного важнее провести правильный анализ, а для этого они должны быть «чисты».
Разбираться в чистоте данных и в основных качественных параметрах я начну с этой статьи.
Для достоверной аналитики должны быть соблюдены все «П» данных: правильные, правильно собранные, собранные в правильной форме, в правильном месте и в правильное время.
Если один из параметров нарушен, это может сказаться на достоверности всей аналитики, а значит нужно понимать, на что важно обращать внимание при работе с данными.
Главные аспекты качества данных
Доступность
У аналитиков должен быть доступ к необходимым данным, но, кроме этого, доступ должен быть и к инструментам, используемым в аналитике.Точность
Все данные должны быть достоверны, а также указаны допустимые погрешности.
Точная температура — хорошие данные, а устаревший адрес, телефон или e-mail — нехорошие данные.Взаимосвязанность
Всегда должна быть возможность связать одни данные с другими. Например, к номеру заказа должна быть привязана информация о клиенте, его адрес, контактная и платежная информации.Полнота
Данные должны быть «жирными» и со всеми частями. «Инвалиды» с отсутствующей частью информации могут помешать получить качественную аналитику.Непротиворечивость
Если данные не согласованы и противоречат друг другу, значит где-то закралась ошибка.
Так если адрес клиента присутствует в двух базах, то он должен совпадать. В противном случае необходимо выбрать один источник достоверным и игнорировать остальные до исправления ошибок.Однозначность
Каждое поле с информацией должно иметь полноценное описание, не допускающее двусмысленных значений.Релевантность
Данные должны соответствовать характеру анализа.
Например, статистика сезонных миграций леммингов слабо относится к сезонным колебаниям биржевых курсов.Тот самый лемминг, не влияющий на биржевые курсы.
Надежность
Надежные данные — это одновременно полная и точная информация.Своевременность
Бич российского бизнеса — несвоевременные данные.
Часто случается, что данные еще не успели обработать и проанализировать, а они уже устарели.С устаревшими данными нельзя работать в построении кратковременной стратегии, их можно использовать только как основу для долгосрочного стратегического планирования и прогнозирования.
Еще один недостаток устаревших данных — они стали уже почти бесполезны, а компания несет издержки по их хранению и обработке.
Ошибка в любом из пунктов может привести к частичной или полной непригодности данных для использования, или, что хуже, к неправильным выводам, сделанным на основе ошибочных данных.
Данные с ошибками
Василиск — в его описании явно закралась ошибка.Ошибки появляются на любом этапе работы с данными, и зачастую аналитики уже не могут повлиять на их исправление, так как данные специалисты являются заключительным звеном в работе с материалом и не могут контролировать сбор и обработку информации.
Давайте разберем основные причины возникновения ошибок и способы, которые помогут их избежать.
Генерация данных
Самая частая и очевидная причина ошибок: тут могут быть как технические причины, так и влияние человеческого фактора.В случае технических причин и сбоев все решается калибровкой и правильной настройкой инструментов сбора информации.
Когда ремонт и калибровка не помогают в решении вопроса и данные продолжают поступать недостоверными, тогда одна из возможных причин — ненадежность приборов.
Так ИК-датчики, измеряющие расстояние до ближайшей стены при картографировании местности, могут давать погрешность метр и более или сбрасывать собранные данные. Доверять показаниям настолько ненадежных датчиков нельзя.
Человеческий фактор также может проявляться по-разному. Например, сотрудники могут не знать как правильно собирать данные или не уметь работать с инструментом, могут быть невнимательными или уставшими, не знать инструкции или неправильно их понимать.
▍ Самое надежное и простое решение — стандартизировать как можно больше этапов процесса сбора данных.
Ввод данных
При ручной генерации данных необходимо их зафиксировать, на этом этапе возникает множество ошибок.
Как бы не расширялся электронный документооборот, многие данные до попадания в компьютер проходят через бумажные носители.Ошибки часто случаются при расшифровке рукописных данных. Большинство исследований по решению ошибок расшифровки проводится в медицинской сфере, так как из-за малейших неточностей под угрозу ставится здоровье и жизнь пациента.
Так исследование показало, что 46% медицинских ошибок обусловлено неточностью при расшифровке рукописных данных. А уровень ошибок в медицинских базах данных достигал 26%, есть предположение, что это связано с тем, что персонал неправильно понял или не смог разобрать написанное от руки.
Так, например, некоторые результаты медицинских опросов населения показывают, что рост взрослого человека может быть 53 см или 112 см. И если в первом случае понятно, что закралась ошибка, и скорее всего рост реципиента был 153 см, то во втором случае рост может быть как правильным, так и ошибочным. При опросах часто встречаются ошибки-очепятки, такие как «аллергия на окошек» или вес 156 кг вместо 56 кг.
В среднем ошибки делятся на четыре типа:
- Запись
Ошибка, при которой данные были изначально записаны неверно. - Вставка
Появление дополнительного символа.
Например: 53,247 ► 523,247. - Удаление
Потеря одного или нескольких символов.
Например: 53,247 ► 53,27. - Перемена мест
Просто берем и меняем два или более символов местами.
Например: 53,247 ► 52,437.
Часто ошибки встречаются в написании дат, а еще чаще при столкновении разных стандартов, таких как американский (месяц/день/год) и европейский (день/месяц/год).
И если иногда ясно, что это ошибка (23 марта — 3/25), то в других случаях она может быть не замечена (3 апреля — 3 / 5 или 5/3?).Как снизить количество ошибок
Гиппогриф — гордое и величественное мифическое животное, разновидность грифонов. Да, на гравюре тоже он, но с ошибками в описании.Первым действием нужно сократить количество этапов генерации данных до ввода. Если вы можете избежать участия бумажного носителя, как передаточного звена, исключайте его.
В электронных формах следует ввести проверку значений, особенно это важно при введении структурированных данных: индекс, номер телефона и код города, БИК, СНИЛС и р/с.Во многих данных есть четкая структура, которая помогает снизить ошибки — это может быть и количество символов, и их разбивка по группам, и иные виды форматов.
▍ При возможности исключайте ручной ввод данных и предлагайте оператору или пользователю выбрать значение из выпадающего списка.
Если же количество вариантов велико, то можно использовать форму вопрос-ответ с заключительным подтверждением правильности введенных данных.
Идеально — исключить человеческий фактор при вводе данных и автоматизировать процесс.
При расшифровке данных хорошо себя зарекомендовал «принцип двойной записи».
При использовании этого метода два сотрудника независимо друг от друга занимаются расшифровкой, а после результаты сравниваются и перепроверяются данные, в которых обнаружены расхождения.Интересный метод проверки данных используется при передаче данных в цифровом формате.
Так, например, в номерах банковских счетов используется контрольное число (сумма).
Контрольное число — это когда после передаваемого номера добавляется число, используемое для проверки данных и обнаружения ошибок.Передаем 941218, а при получении система проводит обратные расчеты и, если сумма не совпадает, то число будет отмечено как ошибочное.
Контрольных чисел может быть несколько, по одному на каждый блок цифр.
У этого метода есть недостатки, связанные с ошибкой перестановки символов, но это лучше чем ничего.
На этом я закончу вводную статью по сбору данных и контролю их качества. Если информация была для вас полезна, то я буду рад обратной связи.Возможно, вы с чем-то не согласны или хотите поделиться своими методами и наработками — приглашаю в комментарии и надеюсь на увлекательное и полезное обсуждение.
Всем спасибо за внимание и хорошего дня!
Простые случаи ошибки ввода/вывода и методы исправления
- Если ошибка возникает при действиях с картой памяти SD (или MicroSD, подключенной через адаптер) или USB флешкой, проверьте, присутствует ли на ней переключатель защиты от записи и не стоит ли он в положении запрета записи («Lock»). Включение такой защиты приводит к рассматриваемой ошибке.
- Если проблем возникает с жестким диском или SSD, подключенным через SATA-интерфейс, попробуйте переподключить, а лучше заменить кабель SATA. Если свободного кабеля нет, можно попробовать временно подключить диск кабелем от необязательного устройства, например, привода DVD. При отсутствии возможности проверки другого кабеля желательно проверить подключение имеющегося как со стороны материнской платы, так и со стороны самого диска.
- При возникновении проблемы при работе с флешкой или внешним жестким диском, попробуйте использовать другие разъемы USB, в том числе разных версий — USB 2.0 и 3.0, в случае ПК — сзади корпуса.
- Учитывайте, что появление ошибки ввода/вывода при подключении внешнего жесткого диска по USB может говорить о недостатке питания (вследствие износа блока питания компьютера или при использовании на ноутбуке при работе от батареи).
- Если ошибка появляется после включения компьютера или ноутбука, но исчезает после перезагрузки, отключите быстрый запуск Windows 10 (подойдет и для 8.1).
- Некоторые пользователи сообщают, что им помогла смена буквы диска, об этом: Как изменить букву диска или флешки в Windows.
Дополнительно, если есть такая возможность, проверьте, как ведёт себя тот же диск на другом компьютере или ноутбуке: если присутствует та же ошибка, мы можем предположить, что дело в самом накопителе, если на нем работает исправно — по всей видимости, проблема на уровне системы или оборудования проблемного компьютера.
И еще один отдельный момент: для случая возникновения ошибки «Запрос не был выполнен из-за ошибки ввода/вывода на устройстве» при работе с USB флешкой, рекомендую ознакомиться с методами из инструкции Флешка пишет, что диск защищен от записи.
Драйверы SATA и USB
Иногда проблема может быть вызвана тем, что в системе не установлены «правильные» для текущей системы драйверы для работы с SATA или USB устройствами. Вместо них — автоматически устанавливаемые Windows совместимые драйверы.
Проверьте, есть ли на официальном сайте вашего ноутбука или материнской платы ПК (именно для вашей модели устройства) доступные драйверы SATA/AHCI/RAID и USB для загрузки. Также имеет смысл загрузить и установить драйверы чипсета. При этом учитывайте, что даже если на вашем компьютере установлена Windows 10, а на сайте доступны драйверы только для предыдущих версий ОС, как правило их можно безопасно установить и они будут исправно работать.
Проверка состояния и ошибок диска
Если проблемный диск виден в системе и ему назначена буква, попробуйте выполнить простую проверку диска на ошибки:
- Запустите командную строку от имени администратора. В Windows 10 это можно сделать, введя «Командная строка» в поиске на панели задач и нажав по соответствующему пункту меню. Другие способы запустить командную строку от Администратора.
- Введите команду, заменив букву диска D на свою (внимание: для жесткого диска процесс может занять несколько часов, не запускайте на ноутбуке, работающем от батареи)и нажмите Enter.
- Дождитесь завершения проверки.
Учитывайте, что проверка при серьезных проблемах с диском или защите от записи может и не запуститься.
Для HDD и SSD стоит также проверить статус S.M.A.R.T. используя для этого соответствующие программы, например, CrystalDiskInfo.
Особое внимание обратите внимание на показания следующих атрибутов (часть из них могут отсутствовать для вашего диска): 05, 0A, C4, C5, C6, С7. Выход этих и других параметров за рамки значений для «здорового» сообщат вам о том, что, вероятно, ошибка вызвана техническим состоянием диска.
Настройка времени ожидания отклика диска в реестре
Этот пункт может быть актуален для подключенных жестких дисков как внутренних, так и внешних, особенно для тех, которые иногда переходят в режим сна.
- Нажмите клавиши Win+R на клавиатуре, введите regedit и нажмите Enter, откроется редактор реестра.
- Перейдите к разделу реестра
- Обратите внимание на значение параметра TimeOutValue в правой панели редактора реестра. Дважды нажав по нему и выбрав десятичное представление, вы можете задать нужное вам значение ожидания в секундах.
По завершении, сохраните сделанные изменения, закройте редактор реестра и перезагрузите компьютер, а затем проверьте, сохраняется ли ошибка.
Видео инструкция
Если диск или флешка сообщает об ошибках ввода вывода на любом компьютере или ноутбуке, при этом контакты на накопителе в порядке (не окислены и не повреждены), есть большая вероятность, что вы имеете дело с аппаратной неисправностью вашего HDD, SSD или USB накопителя и, возможно, оптимальным подходом будет его замена.
Практика не устает доказывать, что в любом ПО самая главная уязвимость — человеческий фактор. И неважно, появился ли баг из-за нехватки квалифицированности специалиста, выжил после долгих часов дебага в поисках ошибки, или считался хитро замаскировавшейся фичей. Среди некоторых разработчиков даже укрепилось мнение, что баги в принципе существуют всегда и везде. Но если ошибки абстрактны и сложно воспроизводимы в реальных условиях, то проблема не является критичной.
В идеальной ситуации баги исправляют все и сразу. Но в жизни всегда есть куча задач, отодвигающих полный и бесповоротный багфикс (новый функционал, срочные хотфиксы, расставленные приоритеты при исправлении багов). Это значит, что в первую очередь находятся и исправляются очевидные и явные проблемы. Остальные тихо ждут своего часа, превращаясь в бомбы замедленного действия. Иногда ошибки приводят не только к неприятностям в жизни рядового разработчика, но и вызывают настоящие катастрофы. Сегодня у нас подборка и объяснение самых кошмарных багов в истории разработки ПО.
Облучение и радиация
Знаменитый случай гибели нескольких человек, получивших смертельную дозу облучения во время сеансов радиационной терапии с применением медицинского ускорителя Therac-25. Ускорители подобного типа используют электроны для создания лучей высокой энергии, высокоточно уничтожающих опухоли. Но некоторые пациенты получили дозы не в несколько сотен рад, как предписывало лечение, а в 20 000 рад; доза в 1000 рад для человека считается несовместимой с жизнью, причем смерть может наступить сразу после облучения.
Всего один программист создал все ПО, используемое в аппаратах Therac — а это 20 тысяч инструкций, написанных на ассемблере. И при этом во всех Therac встречался один тот же пакет библиотек, содержащий ошибки.
Ускоритель Therac-25, ставший третьим в серии успешных аппаратов лучевой терапии, мог работать с рентгеновскими лучами до 25 МэВ. Несколько лет в середине 80-х аппараты Therac-25 работали безупречно, однако со временем начали накапливаться инциденты, повлекшие за собой тяжелые последствия: от ампутации конечностей до гибели пациентов.
Так при определенной последовательности ввода команд с клавиатуры происходил некорректный вызов процедур, влекущих за собой облучение любого произвольного участка тела пациента. Отсутствие на устройстве аппаратного блокиратора критических и продолжительных доз излучения усугубляло проблему.
Иногда Therac-25 при расчете излучения делил на ноль и соответствующим образом увеличивал величины облучения до максимально возможных. Установка булевской переменной в значение «true» производилась командой «x=x+1» из-за чего с вероятностью 1/256 при нажатии кнопки «Set» программа могла пропустить информацию о некорректном положении излучателя.
Если вы разработчик или (что еще лучше) тестировщик, этот случай стоит изучить досконально — есть хорошая статья в wiki, с нее можно начать, а затем ознакомьтесь с большой статьей девятнадцатилетней давности «Мифы о безопасном ПО: уроки знаменитых катастроф». История вобрала в себя большинство классических проблем тестирования.
Как ни печально, но проблемы Therac-25 не остались уникальными. В 2000 году серию аварий вызвал другой софт, точно так же просчитывающий нужную дозу облучения для пациентов, проходящих курс лучевой терапии.
Программное обеспечение Multidata позволяло медицинскому работнику рисовать на экране компьютера порядок размещения металлических блоков, предназначенных для защиты здоровых тканей от радиации. Но софт разрешал использовать только четыре защитных блока, в то время как врачи, в целях повышения безопасности, хотели использовать все пять.
Врачи воспользовались «лайфхаком». Оказалось, что в программе не предусмотрена защита от ввода некорректных данных — можно было нарисовать все пять блоков как один большой блок с отверстием в середине. В медицинском центре онкологии Панамы не понимали, что софт Multidata устанавливал разные показатели конфигурации в зависимости от того, как размещено отверстие: от направления его размещения рассчитывалась правильная доза облучения.
Из-за неверно введенных данных умерли восемь пациентов, в то время как еще 20 получили передозировку, повлекшую серьезные проблемы со здоровьем.Блэкаут
Маленькая ошибка в программном обеспечении системы мониторинга работы оборудования General Electric Energy привела к тому, что 55 миллионов человек остались без электричества. На Восточном побережье США оказались обесточены жилые дома, школы, больницы, аэропорты.
14 августа 2003 года в 0:15 ночи оператор энергетической системы в Индиане с помощью инструмента мониторинга работы оборудования заметил небольшую проблему. Проблема вызвала раздражающий сигнал об ошибке, который оператор выключил. Оператору удалось за несколько минут решить все трудности, но он забыл перезапустить мониторинг — аварийный сигнал остался в выключенном положении.
Отключение сигнала не стало основной причиной блэкаута. Но когда через несколько часов из-за контакта с деревом вырубились провисшие линии электропередачи в Огайо — об этом никто не узнал. Проблема приняла лавинообразный характер, перегруженные линии передачи и электростанции начали вырубаться в Онтарио, Нью-Йорке, Нью-Джерси, Мичигане и далее.
Ни один из операторов не заметил каскад ошибок, которые медленно убивали энергосистему, из-за единственного выключенного сигнала тревоги — никаких дублирующих систем на этот случай не предполагалось.
Mars Climate Orbiter
Mariner 1
В 1962 году космический корабль «Mariner 1» был уничтожен с земли после старта из-за отклонения от курса. Авария возникла на ракете из-за программного обеспечения, в котором разработчик пропустил всего один символ. В результате корабль стоимостью 18 миллионов долларов (в деньгах тех лет) получал неверные управляющие сигналы.
При работе над системой управления ракетой программист переводил рукописные математические формулы в компьютерный код. Символ «верхнего тире» (индекса), он воспринял за обычное тире (или знак минус). Функция сглаживания стала отражать нормальные вариации скорости ракеты как критические и недопустимые.
Однако даже допущенная ошибка могла не привести к критическому сбою, но как назло антенна ракеты потеряла связь с наводящей системой на Земле, и управление взял на себя бортовой компьютер.
Запуск баллистических ракет
26 сентября 1983 года спутник эшелона «Око» системы предупреждения о ракетном нападении СССР ошибочно сообщил о запуске пяти баллистических ракет с территории США. Спутник находился на высокой эллиптической орбите, наблюдая за районами базирования ракет под таким углом, чтобы они находились на краю видимого диска Земли. Это позволяло обнаружить факт запуска на фоне темного космического пространства по инфракрасному излучению работающего ракетного двигателя. Кроме того, выбранное расположение спутника снижало вероятность засветок датчиков отраженным от облаков или снега солнечным светом.
Подобная ошибка, едва не повлекшая за собой глобальный ядерный конфликт, произошла и по другую сторону океана. 9 ноября 1979 года из-за сбоя компьютера воздушно-космической обороны Северной Америки была получена информация о начале ракетной атаки против США — в количестве 2200 запусков. В то же время спутники раннего предупреждения и радары показали, что никакой информации о советской атаке не поступало — только благодаря перепроверке данных, сделанной за 10 минут, не был отдан приказ о взаимном гарантированном уничтожении.
Причиной всему оказалась самая опасная уязвимость — человеческий фактор. Оператор компьютера, находящегося на боевом дежурстве, загрузил в него пленку с учебной программой, имитировавшей ситуацию массированной ракетной атаки.
За несколько первых лет работы Национального центра управления Объединенного командования аэрокосмической обороны США и Канады было зафиксировано 3703 ложных сигнала тревоги, большая часть из которых появилась из-за атмосферных явлений. Однако случались и компьютерные ошибки. Так один из «боевых» компьютеров 3 июня 1980 года показал постоянно меняющиеся цифры количества ракет, запущенных Советским Союзом. Проблема возникла из-за аппаратного сбоя в микросхеме.
Обновление софта и деление на 0
В 1997 американский ракетный крейсер «Йорктаун» (CG-48), на котором были установлены 27 компьютеров (Pentium-Pro на 200 МГц), решил поделить на ноль и полностью вышел из строя.
Компьютеры работали на Windows NT — и работали они ровно так, как вы и ожидаете, узнав название оси. В то время ВМФ США старался максимально широко использовать коммерческое ПО с целью снижения стоимости военной техники. Компьютеры же позволяли автоматизировать управление кораблем без участия человека.На компьютеры «Йорктауна» поставили новую программу, управляющую двигателями. Один из операторов, занимавшийся калибровкой клапанов топливной системы, записал в одну из ячеек расчетной таблицы нулевое значение. 21 сентября 1997 года программа запустила операцию деления на этот самый ноль, началась цепная реакция, и ошибка быстро перекинулась на другие компьютеры локальной сети. В результате отказала вся компьютерная система «Йорктауна». Потребовалось почти три часа, чтобы подключить аварийную систему управления.
Схожая проблема с нулем возникла при испытании истребителя в Израиле. Безупречно работавший самолет на автопилоте пролетел над равнинной частью, над горной частью, над долиной реки Иордан и приблизился к Мертвому морю. В этот момент произошел сбой, автопилот выключился, и пилоты посадили истребитель на ручном управлении.
После долгих разбирательств удалось выяснить, что программы автопилота при вычислении параметров управления производили деление на значение текущей высоты истребителя над уровнем океана. Соответственно, у Мертвого моря, лежащего ниже уровня океана, высота становилась нулевой, провоцируя ошибку.
В мире найдется немало историй, когда обновление софта, совершаемое с самыми благими целями, могло повести за собой множество проблем. В 2008 году атомная электростанция в штате Джорджия (США) мощностью 1,759 МВт в экстренном режиме приостановила работу на 48 часов.
Инженер компании, занимающейся технологическим обслуживанием станции, установил обновление на главный компьютер сети АЭС. Компьютер использовался для слежения за химическими данными и диагностики одной из основных систем электростанции. После установки обновлений компьютер штатно перезагрузился, стерев из памяти данные управляющих систем. Система безопасности станции восприняла потерю части данных как выброс радиоактивных веществ в системы охлаждения реактора. В результате автоматика подала сигнал тревоги и остановила все процессы на станции.
Инцидент с F-22
Самолеты потеряли доступы к данным о количестве топлива, датчикам скорости и высоты, частично нарушилась связь. В течение нескольких часов самые современные истребители Америки летели через океан совершенно беспомощными. В конце концов их удалось посадить только благодаря мастерству пилотов.
Так в чем же была ошибка? Проектировщики из Lockheed Martin даже не рассматривали вопрос о возможности пересечения линии перемены дат — им просто не пришло в голову, что где-то понадобится либо прибавлять, либо вычитать одни сутки.
Другие истории
В этой бескрайней теме есть еще несколько интересных историй. О них сложилось либо неправильное мнение, либо уже были подробные статьи на ГТ и Хабре.
Взрыв на советской газотранспортной системе в 1982 году из-за программных ошибок, заложенных ЦРУ. Эксперты категорически отрицают не только взрыв на газопроводе «Уренгой-Сургут-Челябинск» в 1982 году, но и вообще возможность возникновения такого взрыва.
Алгоритмическая ошибка привела к аварии самолета А-330 — в результате инцидента 119 пассажиров и членов экипажа получили ранения, из них 12 тяжелые.
Ракета-носитель Ariane 5 превратилась в «конфетти» 4 июня 1996 года — ошибка произошла в компоненте ПО, предназначенном для выполнения «регулировки» инерциальной платформы. Потеряно 500 млн долларов (стоимость ракеты с грузом).
Toyota: из-за корявой электроники и софта 89 человек погибли с 2000 по 2010 годы.
Если вы уверены в том, что накопитель, над которым проводятся действия, исправен, сначала рекомендую использовать следующие простые действия:
- Перезагрузить компьютер или ноутбук.
- Если речь идет о внешнем накопителе (USB флешка, карта памяти, внешний жесткий диск) — попробуйте подключить его к другому USB разъему. Желательно на отдельном контроллере, например, используйте USB 2.0 вместо USB 3.0 или наоборот, отдельную группу USB-разъемов. Избегайте использования USB-хабов и передней панели ПК для подключения при рассматриваемой ошибке.
- Если флешка или карта памяти имеют переключатель защиты от записи, убедитесь, что он не установлен в режиме «Lock» (заблокированной записи). Например, для целей написания этой инструкции ошибку я вызывал именно таким способом.
- Если внешний накопитель требует дополнительного питания, учитывайте, что использование адаптеров питания отличающейся от «заводской» мощности может приводить к проблемам, похожим на изучаемую.
- При наличии возможности, проверьте работу и возможность работы в DiskPart с этим же накопителем на другом компьютере: это позволит определить, стоит ли искать причину в диске или же системе.
Дополнительные причины ошибки и способы решения проблемы
К сожалению, описанные выше методы далеко не всегда оказываются работоспособными для ситуации «Программа DiskPart обнаружила ошибку: Запрос не был выполнен из-за ошибки ввода/вывода на устройстве». Следует помнить и учитывать следующие моменты:
- Ошибка может быть вызвана проблемами с подключением устройства: например, неисправный или неплотно подключенный SATA-кабель и кабель питания.
- Неисправный диски на компьютере могут влиять на работу исправных дисков на том же контроллере. Например: на ПК есть несколько SATA-накопителей, один из которых неисправен. В этом случае при обращении к другим (исправным) накопителям тоже могут возникать ошибки.
- Сбои ввода/вывода для жестких дисков на старых (используемых в течение долгого периода времени) компьютерах иногда бывают вызваны проблемам с блоком питания — независимо от номинальной мощности, со временем он может работать нестабильно и не обеспечивать необходимого напряжения/силы тока по отдельным линиям.
- Установите драйверы чипсета, SATA/RAID, USB контроллеров с официального сайта производителя материнской платы вашего компьютера, иногда это может помочь.
- Если речь идет о каком-то «особенном» накопителе, который требует специальных драйверов, убедитесь, что такие драйверы установлены.
- Для USB-флешки и карты памяти при возникновении ошибки ввода/вывода, можно попробовать использовать способы из статьи Что делать, если флешка пишет, что диск защищен от записи, а если это не поможет — использовать специальные программы для ремонта флешки (с потерей данных).
- Крайне редко, но иногда может сработать (если причина ошибки не в самом диске): установите имеющиеся обновления Windows, проверьте целостность системных файлов, используйте точку восстановления системы на дату, когда ошибка не наблюдалась.
И, наконец, часто ошибка бывает вызвана действительной неисправностью HDD, SSD, флешки или карты памяти. Но, прежде чем сделать такой вывод, на всякий случай проверьте, будет ли накопитель работать (для записи, форматирования, изменения структуры разделов) на другом компьютере.
Читайте также: