Подтвердить что ты не робот

Разница между обработкой исключений в С++ и Java?

В Java, если определенная строка кода вызывает сбой программы, тогда исключение поймано и программа продолжает выполняться.

Однако в С++, если у меня есть фрагмент кода, который вызывает сбой программы, например:

try
{
    int x = 6;
    int *p = NULL;
    p = reinterpret_cast<int*>(x);

    *p = 10; // the program crashed here

    cout << "x = " << *p << endl;
}
catch(const char* Message)
{
    cout << "There is an run-time error";
}

Затем программа все еще падает и исключение не попадает.

Итак, какова точка обработки исключений в С++? Я что-то не понимаю?

4b9b3361

Ответ 1

Линия, которая выходит из строя, разыменовывает неверный указатель. В С++ это не вызовет исключения. Вместо этого это поведение undefined.

В С++ не существует ничего, как исключение нулевого указателя, в отличие от Java, которое будет генерировать исключение с помощью null-указателя. Вместо разыменования неверного указателя приведет к поведению undefined. Поведение undefined не всегда означает крах, однако, если он падает, вам повезло.

Обзор языка:

Наконец, и RAII

Одним из наиболее значимых различий между С++ и Java является то, что Java поддерживает оператор finally. Код в блоке finally всегда запускается независимо от того, выполняется ли код в предыдущем блоке catch или нет. Например:

try
{
}
catch (SomeException e)
{
}
finally
{
  //code here is always exectued.
}

Цель выражения finally состоит в том, чтобы позволить очистке программиста в этой точке, то есть выпускать сокеты, закрывать дескрипторы файлов и т.д. Даже несмотря на то, что Java запускает сборщик мусора, сбор мусора применяется только к памяти и другому ресурсу. Есть еще случаи, когда вы должны вручную избавляться от ресурсов. Теперь у С++ нет инструкции finally, поэтому пользователям этого языка рекомендуется придерживаться принципа RAII (Resouce Acquisition is Initialization). У Stroustrup есть объяснение здесь: http://www.stroustrup.com/bs_faq2.html#finally. Я предпочитаю называть его Resource destruction is deallocation, но в основном, когда ваш объект выходит из области видимости, вызывая деструктор, тогда этот деструктор должен освобождать любые ресурсы, которые поддерживает объект.

Например, С++ 11x предоставляет std:: unique_ptr для управления этим:

void foo()
{
  std::unique_ptr<T> t(new T)
  try
  {
    //code that uses t
  }
  catch (...)
  {
  }
}

Ресурс, выделенный через new, будет удален при завершении функции.

уловить все утверждения

Поскольку все исключения в Java наследуются от общего базового класса Exception, если вы хотите, чтобы ваше предложение catch обнаружило какое-либо исключение, затем настройте его следующим образом:

catch (Exception e)
{
  //any exception thrown will land here.
}

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

catch (...)
{

}

Необработанные исключения

Это еще одна область, где языки ведут себя по-разному. В С++ исключенное исключение, которое не поймано, вызовет std:: terminate. std:: завершить действие по умолчанию - вызывать прерывание, которое генерирует SIGABRT, и вся программа останавливается.

В Java поведение заключается в том, чтобы печатать трассировку стека и завершать поток, в котором произошло неперехваченное исключение. Однако, поскольку программист Java может предоставить обработчик UncaughtException, поведение может быть отличным от значения по умолчанию для завершения потока.

Ответ 2

Не все сбои происходят из-за необработанных исключений. Для вашего примера, стандарт С++ говорит, что разыменование указателя NULL приводит к поведению undefined. В Windows вы можете обрабатывать проблемы, которые приводят к краху вашей программы, не вызывая исключение С++ с структурированной обработкой исключений (SEH): __try/__except/__finally. В Unix вы можете настроить специальные signal обработчики.


Кроме того, в вашем коде есть ошибка. Обработчик исключений для const char * будет вызываться только при исключении этого типа. Для стандартных исключений вы должны поймать std::exception или соответствующие подклассы. Чтобы поймать любое исключение С++, используйте catch (...).

Ответ 3

Собственно, вы можете перехватывать системные исключения в С++. Существует опция компилятора (по крайней мере, в Visual Studio), которая позволяет вам выявлять исключения нарушения доступа (поэтому ваша программа сбой).

Java более защищена, что создает иллюзию сложности.

Подумайте о следующем:

В Java:

int x[10];
int i = 20;
try
{
    int k = x[i];
}
catch (ArrayIndexOutOfBoundsException ex)
{
     //will enter here
}

Int С++:

int x[10];
int i = 20;
try
{
    if ( i >= 10 )
        throw new "Index out of bounds";
    int k = x[i];
}
catch (...)
{
    //now it will enter here
}

Все это связано с тем, хотите ли вы оставить больше до среды выполнения (например, в случае Java) или сами хотите обрабатывать вещи. С++ дает вам больше контроля, но вам нужно уделять больше внимания.

Ваша программа Java также выйдет из строя, если исключения не будут обработаны - подумайте об этом, если метод явно выдает исключение, вы не сможете его обработать, потому что компилятор не позволяет вам. Если это явно не указано, ваша программа все равно будет разбита, если она не окружена try/catch.

Если вы спрашиваете, почему системные исключения не могут быть обработаны на С++, я уже ответил: они могут это сделать, по умолчанию это отключено.

Ответ 4

Точка исключений, на любом языке, должна или должна быть обработана исключительные случаи. Но все же случаи, когда вы можете сделать разумные предположения о состоянии глобальной программы и, возможно, восстановление. Ошибки программирования обычно означают, что вы не можете делать никаких предположений о глобальное состояние программы, и должен прервать код так быстро, как возможно, выполнение наименее дополнительного кода (поскольку вы не знаете, что он будет делать).

В Java практически все сообщается с помощью исключения. Все от обычных ожидаемых ошибок ( "файл не найден" при попытке открыть файл) для критических внутренних ошибок (Java.lang.VirtualMachineError). С++ дает вам выбор: если вы обнаружить ошибку кодирования (отказ подтверждения), вы можете прервать процесс немедленно (как правило, более уместно, чем наказывать в неизвестном государство); если "ошибка" - это то, что обычно происходит в ежедневная работа ( "файл не найден" ), вы можете проверить статус или использовать код возврата (опять же, обычно более подходящий, чем исключение). Для количество ситуаций между двумя (например, из памяти), С++ использует исключения.

То, что наиболее подходит в данном приложении, конечно, варьируется: есть случаи, когда "файл не найден" является исключительным (например, если файл является частью приложения, которое не может работать без него), и гарантирует исключение. Аналогичным образом, в определенных случаях нулевой указатель может для управления логикой программы (if ( ptr == NULL ) ...) или соответствуют исключительному случаю (if ( ptr == NULL ) throw ...); в другие случаи, нулевой указатель - это ошибка программирования (assert( ptr != NULL)).

Ответ 5

  • С++ и Java имеют блоки try и catch, но Java имеет один новый блок, который всегда выполняется после try и catch.
  • Java бросает только объекты, но С++ генерирует данные (примитив, указатель и объекты).
  • С++ имеют catch (...) {}, чтобы поймать все исключения всех видов, а Java - catch (Exception e) {}, чтобы поймать все исключения.