исключение C++: бросок станд.:: строка

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

74
задан LogicStuff 21 August 2015 в 10:10
поделиться

5 ответов

Да. std::exception основной класс исключений в библиотеке стандарта C++. Можно хотеть избегать использования строк как классов исключений, потому что они сами могут выдать исключение во время использования. Если это происходит, то, где Вы будете?

повышение имеет превосходное документ о хорошем стиле для исключений и обработки ошибок. Это стоит чтения.

97
ответ дан christopher_f 24 November 2019 в 11:51
поделиться

Несколько принципов:

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

  2. не бросают указатели, но объект, тот способ, которым память обрабатывается для Вас.

Пример:

struct MyException : public std::exception
{
   std::string s;
   MyException(std::string ss) : s(ss) {}
   ~MyException() throw () {} // Updated
   const char* what() const throw() { return s.c_str(); }
};

И затем используют его в Вашем коде:

void Foo::Bar(){
  if(!QueryPerformanceTimer(&m_baz)){
    throw MyException("it's the end of the world!");
  }
}

void Foo::Caller(){
  try{
    this->Bar();// should throw
  }catch(MyException& caught){
    std::cout<<"Got "<<caught.what()<<std::endl;
  }
}
60
ответ дан PierreBdR 24 November 2019 в 11:51
поделиться

Все они работают:

#include <iostream>
using namespace std;

//Good, because manual memory management isn't needed and this uses
//less heap memory (or no heap memory) so this is safer if
//used in a low memory situation
void f() { throw string("foo"); }

//Valid, but avoid manual memory management if there's no reason to use it
void g() { throw new string("foo"); }

//Best.  Just a pointer to a string literal, so no allocation is needed,
//saving on cleanup, and removing a chance for an allocation to fail.
void h() { throw "foo"; }

int main() {
  try { f(); } catch (string s) { cout << s << endl; }
  try { g(); } catch (string* s) { cout << *s << endl; delete s; }
  try { h(); } catch (const char* s) { cout << s << endl; }
  return 0;
}

необходимо предпочесть h f к g. Обратите внимание, что в наименее предпочтительной опции необходимо освободить память явно.

21
ответ дан Patrick M 24 November 2019 в 11:51
поделиться

Это работает, но я не сделал бы этого на вашем месте. Вы, кажется, не удаляете те данные "кучи", когда Вы сделаны, что означает, что Вы создали утечку памяти. Компилятор C++ заботится об обеспечении, что данные исключения поддерживаются, как раз когда стек выталкивается, не чувствуйте, что необходимо использовать "кучу".

Кстати, бросок std::string не является лучшим подходом для начала. У Вас будет намного больше гибкости в будущем при использовании простого интерфейсного объекта. Это может просто инкапсулировать string на данный момент, но возможно в будущем Вы захотите включать другую информацию, как некоторые данные, которые вызвали исключение или возможно номер строки (очень распространенный, это). Вы не хотите изменять всю свою обработку исключений в каждом месте в Вашей кодовой базе, поэтому берете высокую дорогу теперь и не бросаете необработанные объекты.

7
ответ дан Daniel Spiewak 24 November 2019 в 11:51
поделиться

В дополнение к вероятному броску чего-то произошел из станд.:: исключение необходимо бросить анонимные временные файлы и выгоду ссылкой:

void Foo::Bar(){
  if(!QueryPerformanceTimer(&m_baz)){
    throw std::string("it's the end of the world!");
  }
}

void Foo:Caller(){
  try{
    this->Bar();// should throw
  }catch(std::string& caught){ // not quite sure the syntax is ok here...
    std::cout<<"Got "<<caught<<std::endl;
  }
}
  • необходимо бросить анонимные временные файлы так соглашения о компиляторе с объектным временем жизни того, что Вы бросаете - при броске чего-то новый редактор от "кучи" кто-то еще должен освободить вещь.
  • необходимо поймать ссылки для предотвращения объекта, режущего

.

Видят "Эффективный C++ Meyer's - 3-й выпуск" для деталей или посещают https://www.securecoding.cert.org/.../ERR02-A. + Throw+anonymous+temporaries+and+catch+by+reference

7
ответ дан Michael Burr 24 November 2019 в 11:51
поделиться
Другие вопросы по тегам:

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