Обработка ошибок в C

errno – переменная, хранящая целочисленный код последней ошибки. В каждом потоке существует своя локальная версия errno, чем и обусловливается её безопасность в многопоточной среде. Обычно errno реализуется в виде макроса, разворачивающегося в вызов функции, возвращающей указатель на целочисленный буфер. При запуске программы значение errno равно нулю.

Все коды ошибок имеют положительные значения, и могут использоваться в директивах препроцессора #if. В целях удобства и переносимости заголовочный файл <errno. h> определяет макросы, соответствующие кодам ошибок.

Стандарт ISO C определяет следующие коды:

  • EDOM – (Error domain) ошибка области определения.
  • EILSEQ – (Error invalid sequence) ошибочная последовательность байтов.
  • ERANGE – (Error range) результат слишком велик.

Нехитрый скрипт печатает в консоль коды ошибок, их символические имена и описания:

Если вызов функции завершился ошибкой, то она устанавливает переменную errno в ненулевое значение. Если же вызов прошёл успешно, функция обычно не проверяет и не меняет переменную errno. Поэтому перед вызовом функции её нужно установить в 0 .

Как видите, описания ошибок в спецификации функции iconv() более информативны, чем в <errno. h> .

Функции работы с errno

Получив код ошибки, хочется сразу получить по нему её описание. К счастью, ISO C предлагает целый набор полезных функций.

<stdio. h>

void perror(const char *s);

Печатает в stderr содержимое строки s , за которой следует двоеточие, пробел и сообщение об ошибке. После чего печатает символ новой строки ‘\n’ .

<string. h>

char* strerror(int errnum);
Возвращает строку, содержащую описание ошибки errnum . Язык сообщения зависит от локали (немецкий, иврит и даже японский), но обычно поддерживается лишь английский.

strerror() не безопасная функция. Во-первых, возвращаемая ею строка не является константной. При этом она может храниться в статической или в динамической памяти в зависимости от реализации. В первом случае её изменение приведёт к ошибке времени выполнения. Во-вторых, если вы решите сохранить указатель на строку, и после вызовите функцию с новым кодом, все прежние указатели будут указывать уже на новую строку, ибо она использует один буфер для всех строк. В-третьих, её поведение в многопоточной среде не определено в стандарте. Впрочем, в QNX она объявлена как thread safe.

Поэтому в новом стандарте ISO C11 были предложены две очень полезные функции.

size_t strerrorlen_s(errno_t errnum);

Возвращает длину строки с описанием ошибки errnum .

errno_t strerror_s(char *buf, rsize_t buflen, errno_t errnum);

Копирует строку с описание ошибки errnum в буфер buf длиной buflen .

Функции входят в Annex K (Bounds-checking interfaces), вызвавший много споров. Он не обязателен к выполнению и целиком не реализован ни в одной из свободных библиотек. Open Watcom C/C++ (Windows), Slibc (GNU libc) и Safe C Library (POSIX), в последней, к сожалению, именно эти две функции не реализованы. Тем не менее, их можно найти в коммерческих средах разработки и системах реального времени, Embarcadero RAD Studio, INtime RTOS, QNX.

Стандарт POSIX.1-2008 определяет следующие функции:

char *strerror_l(int errnum, locale_t locale);

Возвращает строку, содержащую локализованное описание ошибки errnum , используя locale . Безопасна в многопоточной среде. Не реализована в Mac OS X, FreeBSD, NetBSD, OpenBSD, Solaris и прочих коммерческих UNIX. Реализована в Linux, MINIX 3 и Illumos (OpenSolaris).

int strerror_r(int errnum, char *buf, size_t buflen);

Копирует строку с описание ошибки errnum в буфер buf длиной buflen . Если buflen меньше длины строки, лишнее обрезается. Безопасна в многоготочной среде. Реализована во всех UNIX.

Увы, никакого аналога strerrorlen_s() в POSIX не определили, поэтому длину строки можно выяснить лишь экспериментальным путём. Обычно 300 символов хватает за глаза. GNU C Library в реализации strerror() использует буфер длиной в 1024 символа. Но мало ли, а вдруг?

Макрос assert()

<assert. h>

Макрос, проверяющий условие expression (его результат должен быть числом) во время выполнения. Если условие не выполняется ( expression равно нулю), он печатает в stderr значения __FILE__ , __LINE__ , __func__ и expression в виде строки, после чего вызывает функцию abort() .

Если макрос NDEBUG определён перед включением <assert. h> , то assert() разворачивается в ((void) 0) и не делает ничего. Используется в отладочных целях.

Функции atexit(), exit() и abort()

<stdlib. h>

int atexit(void (*func)(void));

Регистрирует функции, вызываемые при нормальном завершении работы программы в порядке, обратном их регистрации. Можно зарегистрировать до 32 функций.

_Noreturn void exit(int exit_code);

Вызывает нормальное завершение программы, возвращает в среду число exit_code . ISO C стандарт определяет всего три возможных значения: 0 , EXIT_SUCCESS и EXIT_FAILURE . При этом вызываются функции, зарегистрированные через atexit() , сбрасываются и закрываются потоки ввода — вывода, уничтожаются временные файлы, после чего управление передаётся в среду. Функция exit() вызывается в main() при выполнении return или достижении конца программы.

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

_Noreturn void abort(void);

Вызывает аварийное завершение программы, если сигнал не был перехвачен обработчиком сигналов. Временные файлы не уничтожаются, закрытие потоков определяется реализацией. Самое главное отличие вызовов abort() и exit(EXIT_FAILURE) в том, что первый посылает программе сигнал SIGABRT , его можно перехватить и произвести нужные действия перед завершением программы. Записывается дамп памяти программы (core dump file), если они разрешены. При запуске в отладчике он перехватывает сигнал SIGABRT и останавливает выполнение программы, что очень удобно в отладке.

В случае критической ошибки нужно использовать функцию abort() . К примеру, если при выделении памяти или записи файла произошла ошибка. Любые дальнейшие действия могут усугубить ситуацию. Если завершить выполнение обычным способом, при котором производится сброс потоков ввода — вывода, можно потерять ещё неповрежденные данные и временные файлы, поэтому самым лучшим решением будет записать дамп и мгновенно завершить программу.

В случае же некритической ошибки, например, вы не смогли открыть файл, можно безопасно выйти через exit() .

Функции setjmp() и longjmp()

Вот мы и подошли к самому интересному – функциям нелокальных переходов. setjmp() и longjmp() работают по принципу goto, но в отличие от него позволяют перепрыгивать из одного места в другое в пределах всей программы, а не одной функции.

<setjmp. h>

int setjmp(jmp_buf env);

Сохраняет информацию о контексте выполнения программы (регистры микропроцессора и прочее) в env . Возвращает 0 , если была вызвана напрямую или value , если из longjmp() .

void longjmp(jmp_buf env, int value);

Восстанавливает контекст выполнения программы из env , возвращает управление setjmp() и передаёт ей value .

Используя setjmp() и longjmp () можно реализовать механизм исключений. Во многих языках высокого уровня (например, в Perl) исключения реализованы через них.

Внимание! Функции setjmp() и longjmp () в первую очередь применяются в системном программировании, и их использование в клиентском коде не рекомендуется. Их применение ухудшает читаемость программы и может привести к непредсказуемым ошибкам. Например, что произойдёт, если вы прыгните не вверх по стеку – в вызывающую функцию, а в параллельную, уже завершившую выполнение?

Debug card expert коды ошибок

POST-карта или POST-тестер это PCI плата расширения, имеющая цифровой индикатор, который выводит коды инициализации мат. платы. По данному коду можно найти, в каком из компонентов платы имеется неисправность. Коды часто зависят от производителя BIOS. Если ошибки отсутствуют и тест проходит успешно, то POST выдаёт код не меняющийся значение, к примеру на большинстве мат. плат по
завершении инициализации выводится код «FF». Также часто на тестерах установлены светодиоды отображающие напряжения +5 +3,3 +12, −12.

Вашему вниманию коды ошибок, подходящие на самые версии BIOS:

Недавно мне захотелось обзавестись продвинутой и универсальной POST картой, но с учетом ограниченного бюджета. Посидев немного в известных всем интернет магазинах, я наткнулся на китайскую Sintech ST8679 (Debug King). Обзоров или адекватных отзывов в сети по ней не было, а на фото и по описанию она очень походила на ту самую, что я искал. И вот она у меня на руках. Что вышло на самом деле, читайте в обзоре.

Делает POST карту ST8679 китайская компания Sintech Electronic (официальный сайт sintech. cn), уже 10 лет занимающаяся производством компьютерных причиндалов: средства диагностики (читай POST карты) и переходники между различными интерфейсами (могу сказать, есть у них кой чего интересного).

Продукция этой компании (под их и другими брендами) продается по всем интернет магазинам подобных товаров, но есть и два «родных»: www. pc-adapter. net и eshop. sintech. cn. Ни разу в них не покупал, привожу просто для информации и в качестве каталога их продукции, если кому-то интересно.

Но давайте ближе к карте. Ее название «Sintech ST8679«, кроме того, она часто упоминается как «Debug King 3 in 1» (дословно – король отладки). Довольно «громко», но не просто так – это топовая модель из всех POST карт Sintech. Полное официальное описание доступно на странице карты.

Основные особенности из описания POST карты Sintech ST8679:

  • 4 интерфейса: PCI, mini PCI, mini PCI-E, LPC
  • 4 BIOS: Phoenix, Award, AMI, Insyde (зависит от редакции карты и влияет только на отображения текстовых или графических подсказок)
  • Интеллектуальный анализ ошибок и вывод результата на ЖК экран
  • Сегментный индикатор и индикаторы сигналов шины

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

Цена устройства 15-25$ с доставкой (в зависимости от комплекта и жадности продавца).

Комплектация

Об упаковке особо сказать нечего – карточка пришла запаянной в обычный антистатический пакет.

Внутри лежало следующее:

Доставка мою карту не пощадила: погнутые штырьковые контакты на мелкой плате, помятая инструкция со шлейфом, покоцанный корпус дисплея. Спасибо, что дошло…

Инструкция – лист толстой глянцевой бумаги

A3 формата сложенный в несколько раз. Сугубо на ломаном английском, русского нет. В случае утери можно скачать с сайта Sintech (ссылка в начале статьи). Но с имеющейся у меня бумажной версией она немного не совпадает.

Дополнительно комплект может иметь еще 2 шнура:

  1. USB кабель AM-BM (как для принтера). Нужен для почти бесполезного offline режима (об этом чуть далее).
  2. LPC кабель. Служит для подключения mini PCI платы к LPC интерфейсу. Представляет собой 9 разноцветных проводов длиной примерно в 20 см, обжатых в розетку BLS2-9 (шаг контактов 2мм, чуть более редкая, чем обычные BLS). Обратный конец – просто залуженные провода, которые предполагается припаивать по месту.

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

Модуль дисплея

Основным, в своем роде материнским модулем, является модуль дисплея. Он служит для вывода информации о POST кодах подключенной к нему карты. Внешне – пластиковая коробочка размером 22х101х55 мм (ВхШхГ), самый крупный модуль из всего комплекта. Качество пластика – так себе, обычный шероховатый черный китайский пластик.

На лицевой панели находится экран (размером 33х25 мм), 2 кнопки управления и 2 светодиода. На экран наклеена защитная пленка (в углу можно видеть часть лепестка для ее снятия), но снять ее получится только раскрутив корпус модуля.

В этой редакции модуль «перевернули», в инструкциях и старых фото кнопки располагались справа от экрана. Модуль имеет 2 гнезда: слева – 10-контактный IDC для подключения к POST картам, справа – USB.

USB необходим для Offline режима: можно просматривать информацию об имеющихся в базе устройства POST кодах. Своего рода справочник, не более. Операций с компьютером (вроде прошивки, команд и т. д.) не предусмотрено, по крайней мере, такая возможность не документирована.

Действия кнопок:

  1. Вверх-вниз – перелистывание информации о кодах ошибок.
  2. Переключение языка / просмотр редакции прошивки – зажать верхнюю кнопку и, не отпуская ее, нажать нижнюю.
  3. Переключение BIOS – зажав нижнюю кнопку нажимать верхнюю до тех пор, пока не отобразится нужная BIOS.

Подсказки на экране могут выводиться на двух языках: английский и китайский.

В левом нижем углу экрана отображается текущий тип BIOS, для которого выводятся подсказки. Для выбора доступны следующие: Award, AMI, Phoenix, InsydeH2O, AMI EFI (современная версия AMI), Авто режим.

В авто режиме девайс отображает графическую подсказку наиболее вероятной причины ошибки. Строится это на том, что некоторые POST коды разных BIOS совпадают, некоторые наоборот не пересекаются. Для базовой диагностики это неплохо, но с более серьезными проблемами нужен точный код и описание для конкретной BIOS.

На фото возможные варианты подсказок. Внимательный читатель заметит буквы в правом верхнем углу экрана для ошибок памяти. Это отсылка к BIOS, согласно которой предполагается эта ошибка: I – Insyde, P – Phoenix, M – AMI, W – Award, E – AMI EFI.

Экран имеет подсветку, что немаловажно в условиях слабой освещенности. На фоне видно картину на тему «Девушка на пляже», которая не просто отвлекает мыслями о лете, но еще и мешает читать написанное на экране.

Редакция прошивки экранного модуля моей карты (отображается при переключении языка):

Модуль PCI

PCI модуль предназначен для диагностики материнских плат ATX формата, имеющих PCI слот. Может использоваться как сам по себе, так и подключаться к дисплейному модулю. Длина 74 мм, что немного короче PCI слота, но для POST карт это стандартная практика.

Возможности PCI модуля:

  • Считывание и передача POST кода на модуль дисплея
  • Сегментный индикатор для отображения POST кода
  • Светодиодные индикаторы для сигналов шины (Clock, Reset, IRDY, FRAME, DATA, C/BE)
  • Контакты для измерения основных напряжений (+3.3, +12, +5, -12 и GND), что значительно удобней и безопасней, чем замерять напрямую с материнки.

Модуль Mini PCI

Модуль совмещает в себе 3 интерфейса: mini PCI, mini PCI-E, LPC. И предназначен, в первую очередь, для диагностики ноутбуков.

Имейте в виду, что mini PCI значительно короче стандартного (48 мм, вместо 60), как и у других подобных POST карт. Mini PCI-E в пределах спецификации.

Для подключения к LPC служат ряд штырьковых контактов стандарта PLS2 (шаг 2 мм).

Подключается штекером (придется «сочинить» самому, если разъем есть на материнке) или подпаивая соответствующие провода напрямую к контролеру.

Начинка

Приведу фото плат в хорошем разрешении (картинки кликабельны). Старался, чтобы читалась маркировка на всех компонентах (все крупные электролиты – 100μF 16v).

Под наклейкой (на обоих платах) скрывается достаточно древний и известный CPLD чип XC9572XL от Xilinx (даташит на него).

Экранный модуль собран на 4 шурупа PH0.

Фото задней стороны платы:

Для хранения текста и картинок использована 16 мегабитная микросхема Flash памяти с SPI интерфейсом Winbond 25Q16DVSIG. Работает все на 8-битрном микроконтроллере STM 8S003F3P6. Могу сказать, что, судя по фото в сети, в других редакциях использовались другие компоненты.

Индикаторные светодиоды промаркированы Online Offline, а не Offline Online, как написано в инструкции.

ЖК экран VGG090618-6FWNNC от Evervision Electronics разрешением 96×64 точек. Шлейф экрана не съемный, припаян к плате. Подсветка за счет двух SMD светодиодов.

В общем, монтаж не идеальный, флюс отмывать не стали, но для данного ценового сегмента это обычная практика.

Тестирование Sintech ST8679 в работе

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

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

Ну, собственно, все – вставляем карту, включаем материнку и смотрим коды.

Во время прохождения POST, когда на экране «бегут» коды – показания сегментного индикатора и дисплея совпадают.

Когда же POST завершается и остается показание последнего кода, происходит следующее: на дисплее показания не меняются, а на карте «пропадает» один из сегментников, то левый, то правый… Какой-либо зависимости я не нашел. Происходит это стабильно на разных конфигах, независимо от наличия экранного модуля. В общем – глюк, причем из-за него пользоваться PCI платой в одиночку становится проблематичным.

На фото видно еще одну проблему. Карточка, похоже, не является полноценным PCI устройством, и после инициализации генератора (для Award это как раз 26h), BIOS может снять тактирующую частоту с ее слота (проще говоря – «выключить» слот за ненадобностью) и все следующие POST коды просто перестают выводиться. Если я не ошибаюсь, такое поведение свойственно только Award BIOS.

С mini PCI платой все примерно так же. Могу лишь дать парочку советов: 1) она меньше стандартного mini PCI, поэтому плата не будет фиксироваться обеими защелками и может даже выскакивать, поэтому вам нужно обеспечить надежный контакт; 2) в случае, если придется снимать корпус для установки карты – постарайтесь при ее подключении ничего ей не замкнуть, можно подложить кусок бумаги на худой конец.

Во всем остальном работа Sintech ST8679 не отличается от любых других POST карт этого уровня.

Выводы

Однозначно можно сказать, что POST карта Sintech ST8679 ожиданий не оправдала. Главные плюсы: поддержка 4 интерфейсов и внешний дисплей. Во всем остальном это обычная карточка, но с графическим ЖК экраном, который выводит POST код и его описание на английском (что и так можно посмотреть в справочниках и даже на русском). К тому же хватает глюков, но обновление прошивки не предусмотрено.

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

Источники:

https://habr. com/ru/post/324642/

https://web-shpargalka. ru/debug-card-expert-kody-oshibok. php

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: