Re[2]: Про двойной перехват исключений в DLL (оформление код
От: acDev Россия  
Дата: 17.11.20 11:36
Оценка:
Здравствуйте, PM, Вы писали:

PM>Это какая-то древня библиотека с codeproject для печати stacktrace?

Она самая.

PM>Если я ничего не путаю, в ней вроде были утечки памяти.

Погуглил. Вроде было такое. Но очень давно.

PM>Может стоит глянуть на что-то поновее, типа boost::backtrace, которую даже двигают в стандарт.

Из пушки по маленькому воробушку не хочется совсем. Да и мне кажется, что в "мире винды" больше всего юзают именно StackWalker.

PM>Если я правильно понял, нельзя выпускать исключения за пределы экспортируемых из DLL функций, и хочется как-то обрабатывать их?

Верно

PM>Начиная C++11 есть лямбды, для передачи блока кода в другую функцию, так что можно написать функцию которая будет обрабатывать исключения:

Отличная идея!
Как раз лямбды начинаю осваивать. С ними код лаконичным стал.
  Вот что у меня получилось
class my::exception : public std::exception { ... };

class my::DLL { ... };

class my::ExceptInfo { ... };

my::DLL g_dll;

template<typename R, typename F>
auto catch_cpp_exceptions(my::ExceptInfo & einf, R eval, F && func)
{
    try {
        return func();
    }
    catch (my::exception & ex) {
        einf.init(ex);
        throw;
    }
    catch (std::exception & ex) {
        einf.init(ex);
        throw;
    }
    return eval;
}

template<typename R, typename F>
auto catch_exceptions(my::ExceptInfo & einf, R eval, F && func)
{
    __try {
        return catch_cpp_exceptions(einf, eval, std::forward<F>(func));
    }
    __except ( einf.init(GetExceptionInformation(), GetExceptionCode()) ) {
        // nothing
    }
    return eval;
}

int WINAPI DllFunc1(int arg1, int arg2)
{
    #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
    my::ExceptInfo einf(g_dll);
    return catch_exceptions(einf, -1, [&]{ return g_dll.func1(arg1, arg2); });
    // ~einf() -> einf.show()
}    

int WINAPI DllFunc2(int arg1, const char * filename, INT64 * psize)
{
    #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
    my::ExceptInfo einf(g_dll);
    int rc = catch_exceptions(einf, -1, [&]{ return g_dll.func2(arg1, filename, psize); });
    if (einf.is_active()) {
        einf.show(L"filename = '%S'", filename);   // Aux info for user
        if (psize)
            *psize = -1LL;
        return -1;
    }
    return rc;
}

И теперь даже нет необходимости в /EHa. И с указанием /EHsc работает нормально.
Отредактировано 17.11.2020 11:43 acDev . Предыдущая версия . Еще …
Отредактировано 17.11.2020 11:40 acDev . Предыдущая версия .
Отредактировано 17.11.2020 11:37 acDev . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.