Как правильно уловить std и форсировать исключения

Расскажите, как правильно использовать try/catch с boost:: exception.

Это один из примеров

void Settings::init(const std::string &filename)
{
    using boost::property_tree::ptree;
    try 
    {
        read_xml(filename, pt);
    }
    catch(boost::exception const&  ex)
    {
        LOG_FATAL("Can't init settings. %s", /* here is the question */);
    }
}

Нужно ли мне также уловить std:: exception? Я не могу позволить моему приложению выйти из строя, поэтому мне нужно всего лишь зарегистрировать все.

UPD: Я также не могу понять теперь, чтобы извлечь информацию для регистрации из исключения???

Ответ 1

std::exception имеет функцию-член, называемую what(), которая возвращает const char*, которая может объяснить, что произошло. Если вы хотите зарегистрировать его (предположив, что LOG_FATAL обертывает printf каким-то образом), вы можете сделать:

catch(std::exception const&  ex)
{
    LOG_FATAL("Can't init settings. %s", ex.what());
}

Для boost::exception, хотя вы можете использовать boost::get_error_info, чтобы узнать больше об этом.

Ответ 2

вероятно, слишком поздно, чтобы ответить... но

        <...snip...>
        catch (const boost::exception& e)
        {
            std::string diag = diagnostic_information(e);
            // display your error message here, then do whatever you need to, e.g.        
            LOG_FATAL("Can't init settings. %s", diag);
        }
        <...snip...>

Ответ 3

Как и в любом С++, применяется следующее универсальное правило:

Поймать все исключения, которые могут быть выброшены, и только если вы можете их осмысленно отреагировать.

Вы также можете поймать все другие исключения (...) и создать сообщение журнала или что-то в этом роде, но затем вам нужно их сбросить (throw;). Если вы ничего не можете сделать в своем коде, кроме отмены какой-либо операции, вам не нужно обрабатывать исключение. Пусть это пузырь до места, где его можно использовать осмысленно.

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

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

Ответ 4

Это зависит от кода, который вы используете в блоке try. Если код в read_xml может вызывать std:: exception, вам лучше поймать std:: exception. Если вы не уверены, то не может повредить их обоих.

Ответ 5

Вы должны catch использовать только специальные типы исключений, если вы действительно хотите сделать что-то, относящееся к этому типу. В противном случае просто используйте std::exception. Если вы используете код, вы можете выбросить что-то другое, чем catch ... вместо или std::exception.

Если вы хотите обрабатывать несколько (специальных) типов исключений, чем сначала нужно обрабатывать наиболее явные.