2016-09-03 3 views
3

Ну вот мой код исключения:C++ Weird строка/символ поведение * исключение

class OptionNotFoundError: public std::exception { 
public: 
    OptionNotFoundError(std::string option, int position) throw() 
     : option(option), position(position) {} 
    OptionNotFoundError(char option_, int position) throw() 
     : position(position) { option.push_back(option_); } 

    virtual ~OptionNotFoundError() throw() {} 

    virtual const char* what() const throw() { 
     std::string what_str = "Option '" + option + "' not found in position " + std::to_string(position); 
     std::cout << what_str.c_str() << std::endl; 
     return what_str.c_str();; 
    } 

    std::string option; 
    int position; 
}; 

Когда исключение, вот что я получаю в терминале:

terminate called after throwing an instance of 'Args::OptionNotFoundError' 
Option 'c' not found in position 1 
    what(): 

Так cout отлично работает, но ... не возвращение. Если я использую return "smth", он отлично работает.

Страннее: если я заменю what_str определение с

std::string what_str = "test"; 

Я получаю

terminate called after throwing an instance of 'Args::OptionNotFoundError' 
test 
    what(): x�zL� 

Опять же, cout<< работает отлично. Но возвращение ... Не так много. Это ошибка кодирования?

+0

Существует тонны дубликатов для этого UB ... – dasblinkenlight

+2

Рассмотрите возможность создания 'std :: string what_str;' переменной-членом класса 'OptionNotFoundError' вместо локальной переменной внутри функции' what() '. Тогда 'what_str' все еще был бы жив и пинал вместо того, чтобы быть уничтоженным по возвращении. – PaulMcKenzie

ответ

2

Для 1-го случая обратите внимание, что what_str - это локальная переменная внутри what(), она будет уничтожена при выходе из области действия, тогда возвращаемый ею указатель станет болтаться, разыгрывание на нем приводит к UB.

Для 2-го случая, возвращаясь "smth" работает отлично, потому что "smth" является const char[5], который является string literal,

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

Для 3-й случай,

если я заменить what_str определение с

std::string what_str = "test"; 

Это не работает, потому что what_str еще локальная std::string, проблема в том же с 1-м корпусом.

+0

... Правильно. Сначала я написал весь код inline (без «temp» строковых переменных) (и это не сработало лучше), поэтому я не думал о жизни того, что char * указал ... – Salamandar

+0

Я переместил what_str вне того, что() как член класс, который отлично работает ^^ – Salamandar

+0

@Salamandar Да, это действительное решение. Обратите внимание, что любое изменение члена приведет к аннулированию возвращаемого указателя, будьте осторожны. – songyuanyao

4
return what_str.c_str();; 

c_str() возвращает указатель на внутреннее содержание в std::string.

Этот указатель остается в силе только до тех пор, как

  1. Объект std::string разрушается.

  2. Объект std::string изменяется.

std::string объект, из которого получают этот c_str() указатель разрушается, когда ваши возвращения функции.

Это приводит к неопределенному поведению.

const char *, что возвращаемая функция недействительна. Это указывает на внутреннее содержимое разрушенного объекта.

Смежные вопросы