exception handling
От: jyuyjiyuijyu  
Дата: 27.07.11 22:57
Оценка:
Всем привет
делаю некий модуль которому надо как то сообщать об ошибках хочется следующее
например ошибка модуля (логическая или еще какая но своя) просто кинуть код
my_error_gen();
throw excpt(E_BLABLA);

или хочется еще описание свое иногда добавить
my_error_gen();
throw excpt(E_BLABLA, "error description");

или например после вызова системной апи хочу бросить исключение
sys_error_gen();
throw excpt(GetLastError());

или например добавить к нему еще свое описание
sys_error_gen();
throw excpt(GetLastError(), "error description");

вопрос как в обработчике все это разруливать как узнать когда системная ошибка
а когда ошибка модуля ?

первое что приходит на ум
catch (except &e)
{
if (e.LastError & MASK_SYSTEM_ERROR)
    ...
else
    ...
}

а как это правильно сделать ?
вообще как в такой ситуации правильно обработку ошибок сделать ?
какие ограничения: использовать можно весь C рантайм из msvcrt.dll она линкуется как внешняя библиотека
кроме msvcpXX.dll статически ее слинковать тоже нельзя ибо размер прог с компонентом должен быть небольшой
Re: exception handling
От: wander  
Дата: 28.07.11 04:28
Оценка: +1
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>Всем привет

J>делаю некий модуль которому надо как то сообщать об ошибках хочется следующее
J>например ошибка модуля (логическая или еще какая но своя) просто кинуть код
J>...
J>а как это правильно сделать ?
А что, сделать по классу исключений на каждый тип ошибки нельзя?
Re: exception handling
От: ST1 Россия  
Дата: 28.07.11 07:12
Оценка:
На базе кода Деревяго http://ders.stml.net/cpp/intmsg/intmsg.html#1.3 (раздел Исключения и класс CException)
сделал такие макросы, успешно используемые во многих проектах:

#define THROW(MSG) throw newCException(_FLINE_, MSG);

#define CATCH_THROW(MSG) catch (...) { throw newCException(_FLINE_, MSG, toCException(_FLINE_)); }

#define CATCH_LOG()\
    catch(...) {\
        GLOG_ERROR << toCException(_FLINE_)->toStringAll();\
    }

#define CATCH_LOG_RETURN(ret)\
    catch(...) {\
        GLOG_ERROR << toCException(_FLINE_)->toStringAll();\
        return ret;\
    }


Использование универсально для любого msg типа char *

try {
  THROW(msg)
} CATCH_LOG()
t
Re[2]: exception handling
От: Angler Россия  
Дата: 28.07.11 12:19
Оценка: +1
Здравствуйте, ST1, Вы писали:

ST1>
ST1>try {
ST1>  THROW(msg)
ST1>} CATCH_LOG()
ST1>


Re[2]: exception handling
От: Vamp Россия  
Дата: 28.07.11 13:03
Оценка:
ST1>Использование универсально для любого msg типа char *
Какой бесконечный ужас и кошмар...
Да здравствует мыло душистое и веревка пушистая.
Re[3]: exception handling
От: ST1 Россия  
Дата: 28.07.11 13:43
Оценка:
Здравствуйте, Vamp, Вы писали:

ST1>>Использование универсально для любого msg типа char *

V>Какой бесконечный ужас и кошмар...

о std::string такого же мнения?
Re[4]: exception handling
От: Centaur Россия  
Дата: 28.07.11 14:36
Оценка:
Здравствуйте, ST1, Вы писали:

ST1>>>Использование универсально для любого msg типа char *

V>>Какой бесконечный ужас и кошмар...

ST1>о std::string такого же мнения?


Разумеется. У разных исключений должны быть разные типы.
Re[5]: exception handling
От: ST1 Россия  
Дата: 28.07.11 14:50
Оценка:
Ребят, не ленитесь пройти по ссылке и изучить стоящий код, а мой пример лишь иллюстрация возможного использования.
Re: exception handling
От: fdn721  
Дата: 28.07.11 15:16
Оценка: 1 (1) +1
Здравствуйте, jyuyjiyuijyu, Вы писали:

boost::exception
Re[6]: exception handling
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 28.07.11 16:02
Оценка:
Здравствуйте, ST1, Вы писали:

ST1>Ребят, не ленитесь пройти по ссылке и изучить стоящий код, а мой пример лишь иллюстрация возможного использования.

Чтобы не писал этот неизвестный человек, но твой подход с макросами это не С++, а С. Фактически ты пишешь в лог место возникновения ошибки и делаешь return. Это очень напоминает С подход с goto когда есть требование одного входа/выхода из функции. Ты даже не пытаешься обработать ошибку, просто логируешь. Советую прочитать "Совершенный Код" Макконнела галву про исключения и про ошибки.
Sic luceat lux!
Re: exception handling
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 28.07.11 16:11
Оценка: +1
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>Всем привет

J>делаю некий модуль которому надо как то сообщать об ошибках хочется следующее
J>например ошибка модуля (логическая или еще какая но своя) просто кинуть код

J>а как это правильно сделать ?


не понятно что тебе надо логировать ошибку или её обрабатывать? Исключения придуманы как гибкий механизм обработки ошибок, а не логировая. Если ты их просто логируешь, то это надо делать в месте возникновения ошибки. Если ошибка должна быть обработана заведи класс для каждого типа ошибок и отнаследуй от std::exception. То, что ты делаешь похоже на попытку избежать множества if(error) {print(error); return error;}, а не для нормального уведомления пользователя об ошибках.
Sic luceat lux!
Re[7]: exception handling
От: ST1 Россия  
Дата: 28.07.11 16:37
Оценка:
K>Чтобы не писал этот неизвестный человек, но твой подход с макросами это не С++, а С. Фактически ты пишешь в лог место возникновения ошибки и делаешь return. Это очень напоминает С подход с goto когда есть требование одного входа/выхода из функции. Ты даже не пытаешься обработать ошибку, просто логируешь. Советую прочитать "Совершенный Код" Макконнела галву про исключения и про ошибки.

Угу, вот это

try {
...
} CATCH_THROW("Poisson test failed")

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

ERROR: CException [d:\sources\joober\tests\main.cpp:61]: Poisson test failed
CException [d:\sources\joober\poisson\poisson_test.h:38]: Newton failed
CException [d:\sources\cpplib\math\numrecipies\linearsolvers.h:139]: Singular ma
trix in routine ludcmp


Это не обработка по вашему? Да фик с макросами моими, там в коде можно отнаследовать свои типы, все описано, кому надо разберется.
Re[8]: exception handling
От: jyuyjiyuijyu  
Дата: 28.07.11 18:23
Оценка:
подробности ошибки в модуле будут исходить из трех источников
это winapi потом функции wininet.dll и третий HRESULT
сейчас при возникновении winapi ошибки или winhttp
можно бросить так
 
code = call_winhttp_or_winapi_api
if (success != code)
    throw excpt();
или после HRESULT так
hr = call_ole_api
if (success != hr)
{
    SetLastError(hr);
    throw excpt();
}

ловятся все так если надо просто показать сообщение и прибить но в исключении еще код ошибки хранится на случай специальной обработки
catch (excpt &e)
{
    FatalAppExit(0, e.szMsg);
}

вот реализация но чувствую что это адовый велосипед

template<class chType>
class GetWin32ErrorEx
{
    enum{cchSize = 256};
    chType _tszBuf[cchSize];
    DWORD dwError;
public:
    GetWin32ErrorEx(DWORD dwLastError = -1)
    {
        if (dwLastError != -1)
        {
            this->dwError = dwLastError;
        }
        else
        {
            this->dwError = GetLastError();
        }
    }
    
    operator chType * ()
    {
        return select(chType());
    }

private:
    
    wchar_t * select(wchar_t)
    {
        return resolve(_tszBuf);
    }

    char * select(char)
    {
        wchar_t wszBuf[cchSize];
        resolve(wszBuf);
        wnsprintfA(_tszBuf, _countof(_tszBuf), "%S", wszBuf);
        return _tszBuf;
    }

    template<size_t cchSize>
    wchar_t * resolve(wchar_t (&wszBuf)[cchSize])
    {
        DWORD dwLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
        BOOL bOk = FormatMessageW(
            FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, dwError, dwLocale,
            wszBuf, _countof(wszBuf), NULL);
        if (!bOk)
        {
            HMODULE hDll = LoadLibraryExW(L"netmsg.dll", NULL,
                DONT_RESOLVE_DLL_REFERENCES);
            if (hDll)
            {
                bOk = FormatMessageW(
                    FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL, dwError, dwLocale,
                    wszBuf, _countof(wszBuf), NULL);
                FreeLibrary(hDll);
            }
        }

        if (!bOk)
        {
            wnsprintfW(wszBuf, _countof(wszBuf), L"code %#I32x", dwError);
        }
        
        return wszBuf;
    }
};

typedef GetWin32ErrorEx<char> GetWin32ErrorA;
typedef GetWin32ErrorEx<wchar_t> GetWin32ErrorW;
typedef GetWin32ErrorEx<TCHAR> GetWin32Error;


PCCH GetWinHttpError(DWORD dwLastError)
{
    switch (dwLastError)
    {
    case ERROR_WINHTTP_OUT_OF_HANDLES:
        return "ERROR_WINHTTP_OUT_OF_HANDLES";
    case ERROR_WINHTTP_TIMEOUT:
        return "ERROR_WINHTTP_TIMEOUT";
    case ERROR_WINHTTP_INTERNAL_ERROR:
        return "ERROR_WINHTTP_INTERNAL_ERROR";
    case ERROR_WINHTTP_INVALID_URL:
        return "ERROR_WINHTTP_INVALID_URL";

    // ... дальше все ошибки для winhttp.dll to be continued...
    }
    return "WinHttp Unknown";
}

struct excpt
{
    enum{cchSize = 256};
    char szMsg[cchSize];
    DWORD dwLastError;
    
    excpt()
    {
        DWORD dwLastError = GetLastError();
        DWORD dwCode = dwLastError & 0x0000FFFF;
        if (dwCode > WINHTTP_ERROR_BASE && dwCode < WINHTTP_ERROR_LAST)
        {
            // get winhttp error desription
            lstrcpynA(szMsg, GetWinHttpError(dwCode), _countof(szMsg));
        }
        else
        { 
            // get winapi or ole error description
            lstrcpynA(szMsg, GetWin32ErrorA(dwLastError), _countof(szMsg));
        }
        this->dwLastError = dwLastError;
    }
    // сделал этот конструктор для своих ошибок но пока мне хватает и 
    // стандартных из winerror.h 
    excpt(DWORD dwLastError, PCCH pszMessage)
    {
        lstrcpynA(szMsg, pszMessage, _countof(szMsg));
        this->dwLastError = dwLastError;
    }
};
Re: exception handling
От: MescalitoPeyot Украина  
Дата: 28.07.11 19:48
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>вопрос как в обработчике все это разруливать как узнать когда системная ошибка

J>а когда ошибка модуля ?

А зачем?
... << RSDN@Home 1.2.0 alpha 4 rev. 1138>>
Re: exception handling
От: Alexander Pazdnikov  
Дата: 04.08.11 14:13
Оценка: 1 (1) :)
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>а как это правильно сделать ?


По исключениям могу поделиться подборкой ссылок от zaufi
Мне они очень помогли в своё время. Не всё было понятно сразу, но постепенно домедитировал

здесь
Автор: zaufi
Дата: 29.06.06

здесь
Автор: zaufi
Дата: 23.09.08

здесь
Автор: zaufi
Дата: 02.03.11


Очень хорошо расписано про грамотное использование исключений.

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