Выдача нового исключения при выдаче старого исключения

Если деструктор добавляет C++ во время раскручивания стека, вызванного исключением, программа завершается. (Вот почему деструкторы никогда не должны добавлять C++.) Пример:

struct Foo
{
    ~Foo()
    {
        throw 2;   // whoops, already throwing 1 at this point, let's terminate!
    }
};

int main()
{
    Foo foo;
    throw 1;
}

terminate called after throwing an instance of 'int'

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Если наконец блок вводится в Java из-за исключения в соответствующем блоке попытки и что наконец блок выдает второе исключение, первое исключение тихо глотают. Пример:

public static void foo() throws Exception
{
    try
    {
        throw new Exception("first");
    }
    finally
    {
        throw new Exception("second");
    }
}

public static void main(String[] args)
{
    try
    {
        foo();
    }
    catch (Exception e)
    {
        System.out.println(e.getMessage());   // prints "second"
    }
}

Этот вопрос пришел в мою голову: язык программирования мог обработать несколько исключений, бросаемых одновременно? Это было бы полезно? Вы когда-либо пропускали ту способность? Существует ли язык, который уже поддерживает это? Есть ли опыт с таким подходом?

Какие-либо мысли?

5
задан 4 revs 26 April 2010 в 21:25
поделиться

8 ответов

Подумайте в терминах управления потоком. По сути, исключения - это просто причудливые setjmp / longjmp или setcc / callcc в любом случае. Объект исключения используется для выбора определенного места для перехода, например адреса. Обработчик исключения просто рекурсивно обрабатывает текущее исключение, longjmp , пока оно не будет обработано.

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

  • Объединить их в неуловимое исключение. Это означало бы раскрутку всего стека и игнорирование всех обработчиков. Это создает риск каскада исключений, вызывающего совершенно случайное поведение.
  • Каким-то образом построить их декартово произведение. Да правильно.

Методология C ++ хорошо служит интересам предсказуемости.

5
ответ дан 13 December 2019 в 22:04
поделиться

Да, язык может поддерживать одновременное создание нескольких исключений; однако это также означает, что программистам также необходимо обрабатывать несколько исключений одновременно, так что определенно есть компромисс. Я слышал о языках, в которых это есть, хотя у меня возникают проблемы с составлением этого списка в голове; Я считаю, что LINQ или PLINQ могут быть одним из этих языков, но я не совсем помню. В любом случае, есть разные способы создания нескольких исключений ... один из способов - использовать цепочку исключений, либо заставляя одно исключение стать «причиной» или «ранееProgatingException» другого, либо блокируя все исключения. в одно исключение, представляющее тот факт, что было создано несколько исключений. Я полагаю, что язык может также ввести предложение catch, которое позволяет вам указывать сразу несколько типов исключений, хотя это было бы плохим выбором дизайна, IMHO, поскольку количество обработчиков достаточно велико, и это приведет к взрыву предложения catch просто для обработки каждой возможной комбинации.

0
ответ дан 13 December 2019 в 22:04
поделиться

Может ли язык программирования обрабатывает несколько исключений? Конечно, я не понимаю, почему бы и нет. Было бы это полезно? Нет, я бы сказал, что не будет. Обработка ошибок и возобновление работы и так очень сложны - я не понимаю, как добавление комбинаторного взрыва к проблеме могло бы помочь.

2
ответ дан 13 December 2019 в 22:04
поделиться

C ++ std :: exception_ptr позволяет сохранять исключения. Таким образом, должна быть возможность встраивать исключения в другие исключения и создавать впечатление, что у вас есть стек для выброшенных исключений. Это может быть полезно, если вы хотите узнать основную причину фактического исключения.

0
ответ дан 13 December 2019 в 22:04
поделиться

Вы можете связать исключения. http://java.sun.com/docs/books/tutorial/essential/exceptions/chained.html

try {

} catch (IOException e) {
    throw new SampleException("Other IOException", e);
}

Вы также можете попробовать уловить внутри вашего финнала.

try{
}catch(Exception e){
}finally{
    try{
      throw new SampleException("foo");
    }catch(Exception e){
    }
}

Редактировать:

Также у вас может быть несколько захватов. Я не думаю, что несколько исключений было бы хорошей идеей, потому что исключение - это уже то, от чего вам нужно восстанавливать. Единственная причина иметь более одного исключения, о котором я могу думать, заключается в том, что вы используете его как часть своей логики (например, множественный возврат), что будет отклоняться от первоначальной цели идеи исключения. Кроме того, , как можно создать два исключения одновременно?

3
ответ дан 13 December 2019 в 22:04
поделиться

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

  • Если тест не проходит, генерируется исключение (либо созданное тестируемым кодом, либо утверждением).
  • Каждый метод @After вызывается после теста, независимо от того, завершился ли тест успешно.
  • Если метод After не работает, генерируется другое исключение.
  • В моей среде IDE (Eclipse) для результата теста отображается только исключение, созданное в методе After.

Я знаю, что JUnit уведомляет своих тестовых слушателей об обоих исключениях, и при отладке теста в Eclipse я вижу, что первое исключение появляется в представлении JUnit, но вскоре после этого оно заменяется вторым.

Эту проблему, вероятно, следует решить, заставив Eclipse запоминать все уведомления для данного теста, а не только последнее. Наличие «параллельных исключений», когда исключение из finally не поглощает исключение из try , также решило бы эту проблему.

0
ответ дан 13 December 2019 в 22:04
поделиться

Если подумать, то в описанной вами ситуации Exception("First") концептуально является первопричиной Exception("second"). Наиболее полезным для пользователя было бы, вероятно, получить дамп стека, показывающий цепочку в таком порядке...

0
ответ дан 13 December 2019 в 22:04
поделиться

В управляемых платформах я могу подумать о ситуациях, когда может быть полезно, чтобы утилизатор "поднимал" исключение до чего-то более сильного, но не полностью фатального для приложения. Например, утилизатор объекта "command" может попытаться развернуть состояние связанного с ним соединения, чтобы отменить любые частично выполненные команды. Если это сработает, основной код может попытаться выполнить другие действия с соединением. Если попытка "отмены" не сработала, исключение, вероятно, должно распространиться до уровня, на котором соединение было бы уничтожено. В таком случае может быть полезно, чтобы исключение содержало "внутреннее исключение", хотя единственным известным мне способом добиться этого было бы размещение попытки отмены в блоке catch, а не в блоке "finally".

0
ответ дан 13 December 2019 в 22:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: