Перейти к содержанию
    

Коды завершения функции

Иногда приходится придумывать некие коды, информирующие о той или иной ошибке при выходе из функции. К EXIT_SUCCESS и EXIT_FAILURE добавляются дополнительные. Не задавались ли вы целью привести коды в систему, чтобы пользоваться во всех случаях? Если да, поделитесь, пожалуйста идеями.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хорошие коды. Но для встроенной программы избыточны. Я предполагаю использовать максимум 8, и то не знаю, зачем мне столько. Есть у кубовского HAL 4 значения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я обычно пишу модульно. То есть есть драйвер, допустим, EEPROM-памяти. Он оформлен парой файлов EEPROM.c и EERPOM.h.

Ну и для каждого драйвера свои сигнатуры завершения функций.

unsigned int ReturnValue = EEPROM_LoadParameters(&EEPROM);
if(ReturnValue == EEPROM_LOAD_ERROR_CRC)
  printf("WARNING! The EEPROM checksum does not match!\n\n\r");
else if(ReturnValue == EEPROM_LOAD_ERROR_ID)
  printf("WARNING! Installed someone else's EEPROM. Read and write operations will be invalid!\n\n\r");

В файле EEPROM.h при этом где-то в самом верху:

#define EEPROM_LOAD_OK        0
#define EEPROM_LOAD_ERROR_CRC 1
#define EEPROM_LOAD_ERROR_ID  2

Но еще лучше сделать их не #define-ми, а enum-ами. В отладчике проще жить станет.

 

Ну а вот так, допустим, у меня выглядит заголовочный файл драйвера обмена:

#ifndef _EXCHANGE_H_
#define _EXCHANGE_H_

#define EXCHANGE_RECEIVE_BUFFER_SIZE 32

#define EXCHANGE_RECEIVE_OK 0
#define EXCHANGE_RECEIVE_ERROR 1

#define EXCHANGE_TRANSMIT_OK 0
#define EXCHANGE_TRANSMIT_ERROR 1

#define EXCHANGE_MESSAGE_HANDLING_OK 0
#define EXCHANGE_MESSAGE_HANDLING_ERROR 1

// структура дескриптора транзакций
typedef struct
{
 void               *Data;
 volatile unsigned int  Size;
}TExchangeDescriptor;

// структура принимаемых сообщений
typedef struct
{
 #define EXCHANGE_RECEIVE_COMMAND_SYSTEM_RESET 0x12345678
 unsigned int Command;
}TExchangeReceiveMessage;

// функция приема данных по внешнему каналу обмена
unsigned int EXCHANGE_ReceiveData(TExchangeDescriptor *ExchangeRxDescriptor, unsigned int Timeout);
// функция отправки данных по внешнему каналу обмена
unsigned int EXCHANGE_TransmitData(TExchangeDescriptor *ExchangeTxDescriptor);
// функция обработки принятых сообщений
unsigned int EXCHANGE_ReceiveMessageHandler(TExchangeReceiveMessage *ExchangeReceiveMessage);

#endif

Я обычно в коде логгирую все исключительные ситуации или просто поведение системы в критических участках или интересующих меня местах, поэтому в коде довольно просто писать лог (см. первый блок кода). Но это все дело вкуса, ИМХО.

Изменено пользователем Arlleex

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Меня немного смущает, что имя тип возвращаемого кода выглядит "солиднее" имени самой функции.

fpgaConfigRetcode_t Fpga_config(void)

 

В HAL имеется следующее:

typedef enum

{

HAL_OK = 0x00U,

HAL_ERROR = 0x01U,

HAL_BUSY = 0x02U,

HAL_TIMEOUT = 0x03U

} HAL_StatusTypeDef;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, вот такой набор прикинул, скомпилировал из разных источников. Годится?

typedef enum {

SUCCESS_OK, // 0

ERROR_GENERAL_FAILURE, // 1 _UNSPECIFIED

ERROR_INVALID_FUNCTION, // _INVALID_HANDLE, _NOT_IMPLEMENTED

ERROR_INVALID_PARAMETER, // _INVALID_ARGUMENT, _BAD_COMMAND

ERROR_NOT_FOUND, // _FILE, _PATH

ERROR_DEVICE_FAILED, // _DEVICE_NOT_EXIST

ERROR_INVALID_ACCESS, // _ACCESS_DENIED, _LOCK

ERROR_NOT_READY, // _BUSY, _LOCK

ERROR_TIMEOUT,

ERROR_MEMORY, // _OUT_OF_MEMORY, _BUFFER_EXCEEDED

ERROR_POINTER,

ERROR_INVALID_DATA, // _READ_FAULT

ERROR_WRITE_FAULT,

ERROR_PROTECT, // _WRITE_PROTECT

ERROR_VERIFY, // _INVALID_CRC, _INVALID_PASSWORD

ERROR_UNEXPECTED // _ABORT

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, вот такой набор прикинул, скомпилировал из разных источников. Годится?

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

enum TRetVal {
    /* Common result values */
    rvOK = 0x00,        // Операция завершена без ошибок
    rvFAILED = 0x01,        // Операция завершена с ошибкой (общая ошибка)
    rvCRC_FAILED = 0x02,        // Подсчитанная КС неверна
    rvSETTING_ERROR = 0x03,     // Параметры настроек заданы неверно
    rvTIME_OUT = 0x05,      // Операция завершена с таймаутом
    rvUSER_CANCEL = 0x06,       // Выполнение операции прервано пользователем
    rvPARAM_INCORRECT = 0x0b, /** В функцию переданы неверные параметры */
    rvVIRT_FUNC = 0x0c, /** Функция виртуальная, нет реализации */
    rvNULL_POINTER = 0x0d, /** Попытка обратиться по нулевому указателю */
    rvBUSY = 0x0f, /** Процесс занят */
    rvNOT_CONNECTED = 0x11, /* Соединение не установлено */
    rvOUT_OF_MEMORY = 0x12, /* Закончилась память в куче */

    /*CIRCLE BUFFER*/
    rvBUFFER_OVERFLOW = 0x57, /** Переполнение буфера */
    rvBUFFER_EMPTY = 0x58, /** Буфер данных пуст */
    rvBUFFER_FULL = 0x59, /** Буфер данных заполнен */

    /* Measure core */
    rvOFFSET_ERROR = 0x60, /** Погрешность смещения в одном из токовых каналов */
    rvCANT_CALIBRATE = 0x61, /** Невозможно откалибровать */
    rvNOT_CALIBRATED = 0x62,        // Прибор не откалиброван
    rvALRDY_RUN = 0x63, /** Сбор данных уже запущен */
    rvALRDY_STOPPED = 0x64, /** Сбор данных уже остановлен */

    /* Non-Volatile Memory */
    rvDISK_WRITE_ERROR = 0x70, /** Ошибка записи в микросхему памяти */
    rvDISK_NOT_FOUND = 0x71, /** Не найдена микросхема памяти */

    /* Drivers */
    rvCLOSE = 0x80, /* Устройство закрыто */
    rvOPEN_ERROR = 0x81, /* Ошибка открытия драйвера, например не можем считать ID-микросхемы*/
};

И всё равно не редки ситуации, когда выясняется, что какому-то уникальному модулю нужен свой код ошибки, которого ещё нет. И приходится добавлять. Кстати, у меня ещё вопрос: а как по возвращаемому значению идентифицировать функцию, где произошла ошибка? Так сказать "размотать стек"?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

И всё равно не редки ситуации, когда выясняется, что какому-то уникальному модулю нужен свой код ошибки, которого ещё нет. И приходится добавлять. Кстати, у меня ещё вопрос: а как по возвращаемому значению идентифицировать функцию, где произошла ошибка? Так сказать "размотать стек"?

Спасибо, изучу. Идентифицировать буду сразу по возвращению из вызываемой функции, не дожидаясь завершения работы вызывающей функции.

Мне столько кодов не нужно. А если случится непредвиденная ошибка, можно выдать код из наиболее подходящих, или unspecified.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, вот такой набор прикинул, скомпилировал из разных источников. Годится?

Если пишете для себя - делайте как угодно. Если есть хоть малейшая вероятность, что с вашим кодом будут работать другие люди, то лучше возьмите любой из стандартов, таким, какой он есть, полностью и без самодельных улучшений.

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если пишете для себя - делайте как угодно. Если есть хоть малейшая вероятность, что с вашим кодом будут работать другие люди, то лучше возьмите любой из стандартов, таким, какой он есть, полностью и без самодельных улучшений.

Я всегда делаю для себя. Но так, чтобы другим было не стыдно показать. :biggrin:

Писал выше, мне много кодов не надо. Сначала хотел 4, потом 8, остановлюсь на 16. Полбайта займет, цэ гарно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я всегда делаю для себя. Но так, чтобы другим было не стыдно показать. biggrin.gif

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

Изменено пользователем one_eight_seven

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, у меня ещё вопрос: а как по возвращаемому значению идентифицировать функцию, где произошла ошибка? Так сказать "размотать стек"?

Возвращать PC/LR и по мап файлу смотреть что откуда?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Иногда приходится придумывать некие коды, информирующие о той или иной ошибке при выходе из функции. К EXIT_SUCCESS и EXIT_FAILURE добавляются дополнительные. Не задавались ли вы целью привести коды в систему, чтобы пользоваться во всех случаях? Если да, поделитесь, пожалуйста идеями.

Идея одна - у всех функций коды разные. Тем более функции живут на разных уровнях иерархии. Группировать смысла немного.

Поэтому есть 0 = SUCCESS, остальные коды пишутся и обзываются по порядку появления в функции.

Название формирую из уровня иерархии, например HAL_ плюс библиотека _UART и сокращенное название. Сокращенные названия можно брать из стандартных систем, типа Windows/UNIX

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...