Повторное создание нового исключения с тем же сообщением приводит к выводу мусора. Почему? - PullRequest
0 голосов
/ 07 октября 2019

Я хочу перехватить исключение, чтобы дополнительно указать сообщение об ошибке, а затем выдать новое исключение с этим расширенным сообщением. Однако это приводит к выводу мусора. Почему?

Вот MWE:

#include <iostream>
#include <string>
#include <exception>

class myError : public std::exception
{
private:
    std::string m_error;

public:
    explicit myError( const std::string& error ) :
        m_error { error }
    {}
    explicit myError( const char* error ) :
        m_error { error }
    {} 

    const char* what() const noexcept override
    {
        //return m_error.c_str();
        return ("My error: " + m_error).c_str();
    }
};


int main()
{
    try{
        try{
            throw myError ( "Error message" );
        } catch ( const std::exception& e ) {
            throw myError( e.what() );
        }
    } catch ( const std::exception& e ) {
        std::cout << e.what() << "\n";
    }


    return 0;
}

Я ожидаю, что на выходе будет «Моя ошибка: Моя ошибка: сообщение об ошибке», но вместо этого это короткая последовательность случайных символов,предположительно, до тех пор, пока не будет нажата \0.

Если я не добавлю сообщение внутри myError::what() (т. е. строку, которая закомментирована), то вывод будет просто «Сообщение об ошибке», так что все работает как положено,Почему это происходит?

Я запускаю gcc 8.1.0 в Windows с x86_64-posix-seh-rev0 в качестве параметров установки.

И я в некоторой степени осведомлен о nested_exception ичто я теряю некоторую информацию о трассировке и т. д.

РЕДАКТИРОВАТЬ: В качестве обходного пути добавление сообщения «Моя ошибка» внутри конструктора дает ожидаемый результат:

    explicit myError( const std::string& error ) :
        m_error { "My error: " + error }
    {}
    explicit myError( const char* error ) :
        m_error { "My error: " + std::string{ error } }
    {}

    const char* what() const noexcept override
    {
        return m_error.c_str();
    }

Так что-топохоже не так с return ("My error: " + m_error).c_str();.

1 Ответ

4 голосов
/ 07 октября 2019

In:

return ("My error: " + m_error).c_str();

... c_str() возвращает указатель на внутренний буфер временной строки, созданной конкатенацией. Время жизни этой строки заканчивается сразу после оператора return, в результате чего возвращаемый указатель зависает и его использование не определено.

...