LINUX.ORG.RU

Валится на throw


0

0

Разве так нельзя писать?

-----------------------------------------------------------------
#include <exception>
#include <iostream>

class my_error: public std::exception {
private:
        std::string m_err;
public:
        my_error(const std::string &err) throw() : m_err(err) {}
        ~my_error() throw() {}
        virtual const char* what() const throw() { return m_err.c_str(); }
};

int main(void)
{
        try     {
                throw my_error("FATAL ERROR");
        }
        catch(my_error &e)      {
                std::cout << "exception handled: " << e.what() << std::endl;
        }

        return 0;
}
-----------------------------------------------------------------

Если компилирую кросскомпилятором sh4-linux-gcc v3.0.3 - валится по сегфолту на throw
Компилирую gcc v3.4.3 - все работает.


Это работает и там и там:
-----------------------------------------------------------------
#include <exception>
#include <iostream>

class my_error: public std::exception {
private:
        const char *m_err;
public:
        my_error(const char *err) throw() : m_err(err) {}
        ~my_error() throw() {}
        virtual const char* what() const throw() { return m_err; }
};

int main(void)
{
        try     {
                throw my_error("FATAL ERROR");
        }
        catch(my_error &e)      {
                std::cout << "exception handled: " << e.what() << std::endl;
        }

        return 0;
}
-----------------------------------------------------------------

бага компилятора ИМХО, да и твой класс можно упростить до:

class my_error: public std::exception {
public:
my_error(char const * err) throw() : exception(err) {}
};

:)

aton
()
Ответ на: комментарий от aton

У меня не упрощается:

---------------------------------------------------------------
$ cat extest1.cpp
#include <exception>
#include <iostream>

class my_error: public std::exception {
public:
        my_error(char const * err) throw() : exception(err) {}
};

int main(void)
{
        try     {
                throw my_error("FATAL ERROR");
        }
        catch(my_error &e)      {
                std::cout << "exception handled: " << e.what() << std::endl;
        }

        return 0;
}
---------------------------------------------------------------
$ g++ extest1.cpp -o extest1
extest1.cpp: In constructor `my_error::my_error(const char*)':
extest1.cpp:6: error: no matching function for call to `std::exception::exception(const char*&)'
/usr/local/lib/gcc/i686-pc-linux-gnu/3.4.3/../../../../include/c++/3.4.3/excepti
on:53: note: candidates are: std::exception::exception(const std::exception&)
/usr/local/lib/gcc/i686-pc-linux-gnu/3.4.3/../../../../include/c++/3.4.3/excepti
on:55: note:                 std::exception::exception()
---------------------------------------------------------------

Из <exception>:
---------------------------------------------------------------
namespace std
{
  class exception
  {
  public:
    exception() throw() { }
    virtual ~exception() throw();
    /** Returns a C-style character string describing the general cause
     *  of the current error.  */
    virtual const char* what() const throw();
  };
...
---------------------------------------------------------------

vasirck
() автор топика

1. наследуйся от std::runtime_error - оно делает именно то что тебе надо.

2. берем в ручки gdb и смотрим backtrace когда падает, возможно std::string кидает exception в copy ctor или этот sh4 криво понимает exception specifications.

3. дурная идея, но вдруг этот sh4 не инклудит std::string вместе с exception, и string - undefined, и оно каким-то образом компилируется даже, ну и падает ессно.

AnToXa
()
Ответ на: комментарий от AnToXa

Странно, седня работает и не валится, ничего не менял.

Посмотрел runtime_error - понял, что конструктор надо без throw() описывать, т.к. конструктор string может исключение кинуть.

vasirck
() автор топика
Ответ на: комментарий от vasirck

Компилятор в созданном им конструкторе копии производит копирование путем почленной инициализации. Это не всегда применимо.

Поскольку во втором примере текст ошибки - это указатель на чар - то всё работеает(почленная инициализация в конструкторе копирования предоставленным компиляторм)

В первом коде важно, чтобы класс имел явно определенный конструктор
копирования, и копировал значение переменной, содержащей текст ошибки...

в первом примере ты обязан обявить конструктор копирования...

dlomin
()
Ответ на: комментарий от aton

если const char* m_err; - конструктор копирования по умолчанию отработает корректно

если std::string m_err; - конструктор копирования по умолчанию отработает некорректно;

dlomin
()
Ответ на: комментарий от dlomin

> если std::string m_err; - конструктор копирования по умолчанию
> отработает некорректно;

Скажи откуда такие познания?! Ты сильно заблуждаешся!!!


В стандарте, в пункте 12.8(8) написно такое, примерно такое:

Если подобъект это класс, то для него будет вызван
его собственный констуртор копии.

Во как :)


aton
()
Ответ на: комментарий от dlomin

но, я не раз получал вот такое непредсказуемое поведение именно с классами наследниками exception, если руками не прописать конструктор копирования

поэтому уже давно привык описать конструктор копирования, и дело с концом..




dlomin
()
Ответ на: комментарий от aton

>твой класс можно упростить до: > >class my_error: public std::exception { >public: >my_error(char const * err) throw() : exception(err) {} >}; > >:)

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

Не советую так писать.

anonymous
()
Ответ на: комментарий от anonymous

Да не тут все проще, я работаю с Dinkumware а там std::exception
немного отличается от STLPort версии. Хотя и не по стандарту, но
там есть конструктор std::exception(char const *)

aton
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.