Есть ли лучший способ обработки исключений? блок try-catch действительно уродлив - PullRequest
4 голосов
/ 16 июня 2020

Я прочитал этот и обнаружил, что важно обрабатывать исключения, я использую nlohmann::json (из github ), и почти в большинстве моих функций-членов используется nlohmann::json::parse и nlohmann::json::dump, что дает возможность генерировать исключения, если на входе есть проблема.

Итак, мне нужно обработать этот шанс выброса исключения примерно так:

bool my_class::function(const std::string& input) const
try
{
    using namespace nlohmann;

    const auto result = json::parse(input);
    const auto name = result["name"].dump();

    /* and ... */
}
catch (const std::exception& e)
{
    /* handle exception */
}

Но я хочу знать, какая строка кода выдает исключение, поэтому, если я напишу что-то вроде этого:

bool my_class::function(const std::string& input) const
{
    using namespace nlohmann;

    try
    {
        const auto result = json::parse(input);
    }
    catch(const std::exception& e)
    {
        /* handle exception */
    }

    try
    {
        const auto name = result["name"].dump();
    }
    catch(const std::exception& e)
    {
        /* handle exception */
    }

    /* and ... */
}

У меня остались тысячи блоков try-catch. Почему лучше обрабатывать исключение?

Ответы [ 2 ]

5 голосов
/ 16 июня 2020

Я бы go вот так: установил "указатель последовательности", чтобы записывать, где / что вы пытаетесь проанализировать, например, со строкой с шаблоном , пытающейся проанализировать .. . , чтобы вы могли узнать / уведомить, где именно был неисправный элемент в json.

посмотрите в примере ниже, если "имя ошибочно, тогда r содержит значение" пытается проанализировать имя ", поэтому в исключении у вас есть информация о том, какой элемент json вызывает проблему :)

bool my_class::function(const std::string& input) const
{
    std::string r{""};
    try
    {
        using namespace nlohmann;
        r="trying to parse input";
        const auto result = json::parse(input);

        r="trying to parse name";
        const auto name = result["name"].dump();

        r="trying to parse age";
        const auto age = result["age"].dump();

        /* and ... */
    }
    catch (const std::exception& e)
    {
        /* handle exception */
    }
}
3 голосов
/ 16 июня 2020

Как вы могли заметить, в C ++ эта информация недоступна. @ ΦXocę 웃 Пepeúpa ツ предоставляет хороший обходной путь.

Позвольте мне высказать другую точку зрения, как конечный пользователь вашей программы, меня не интересует строка кода, в которой программа не работает. Либо JSON, который я предоставляю, правильный или неверный. Во втором случае я хочу знать, что мне нужно сделать, чтобы исправить ошибку JSON. Глядя на код , определяющий исключения, он выглядит очень подробным.

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

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

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

...