Создание нового исключения при создании старого исключения - PullRequest
5 голосов
/ 27 апреля 2010

Если деструктор создает 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.

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

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"
    }
}

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

Есть мысли?

Ответы [ 8 ]

5 голосов
/ 27 апреля 2010

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

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

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

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

3 голосов
/ 27 апреля 2010

Вы можете связать исключения. 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){
    }
}

Edit:

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

2 голосов
/ 27 апреля 2010

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

0 голосов
/ 07 июля 2010

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

0 голосов
/ 06 июля 2010

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

0 голосов
/ 27 апреля 2010

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

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

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

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

0 голосов
/ 27 апреля 2010

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

0 голосов
/ 27 апреля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...