#c #linux #c 11 #g
#c #linux #c 11 #g
Вопрос:
Проблема
У меня есть GLSLFailedToLoadException, которое является производным от класса исключений GlHelperException.
GlHelperException имеет функцию виртуального броска для описания ошибки с помощью свойства title исключения и номера строки с именем файла.
Но когда я тестирую исключение в основной функции, блок catch не печатает правильный журнал отладки функции what() и возвращает terminate, вызванный после создания исключения GLSLFailtedToLoadException.
Определение исключения
class GlHelperException: public std::exception{
public:
virtual const char* what() const throw(){
return (std::string(this->title)
" - in file "
std::string(this->filename)
" at line "
std::to_string(this->line)).c_str();
}
protected:
const char *title;
const char *filename;
int line;
};
class GLSLFailedToLoadException: public GlHelperException{
public:
GLSLFailedToLoadException(const char *filename, int line);
};
GLSLFailedToLoadException::GLSLFailedToLoadException(const char *filename, int line){
this->filename = filename;
this->line = line;
this->title = "Failed to load and compile GLSL program ";
}
Сайт тестового выброса
int main(int argc, char **argv){
/* Irrelevant Code*/
try{
throw new GLSLFailedToLoadException(__FILE__, __LINE__);
}
catch(GLSLFailedToLoadException amp;e){
std::cout<<"Exception Caught"<<std::endl;
std::cout<<e.what()<<std::endl;
}
return 0;
}
Фактические результаты
terminate called after throwing an instance of 'GLSLFailedToLoadException*'
Aborted (core dumped)
Ожидаемые результаты
Failed to load and compile GLSL program in __FILE__ at __LINE__
Комментарии:
1. В вашем
GLSLFailedToLoadException
конструкторе вам действительно следует использовать список инициализации, а не тело конструктора. Также затем измените своиconst char *
члены наconst std::string
s, чтобы вы фактически делали копию переданных значений, а не просто сохраняли указатели, которые вот-вот станут недействительными.
Ответ №1:
Вы создаете указатель на объект, но пытаетесь перехватить объект (по ссылке).
Измените свой throw
оператор, чтобы создать объект:
throw GLSLFailedToLoadException(__FILE__, __LINE__);
Я бы также рекомендовал всегда делать catch
исключения по const
ссылке, поэтому:
catch (const GLSLFailedToLoadExceptionamp; e)
Поскольку ваш код в данный момент написан, вам не удается перехватить исключение, и оно, таким образом, уходит main()
, в результате чего вы видите результат — неперехваченное исключение, завершающее программу.
Вам также необходимо использовать std::string
s в вашем объекте исключения вместо указателей ( const char *
), потому что указатели, которые вы храните в данный момент, не сохраняются в течение всего срока действия объекта, поэтому вам нужно сделать копии строк, на которые указано.
Комментарии:
1. Но теперь на выходе получается пойманное исключение
2. Журнал отладки не печатается
3. @SiddharthSingh : Изменить
const char *title;
иconst char *filename;
бытьstd::string
. Вы не можете просто хранить эти указатели.4.@SiddharthSingh Это совершенно другая проблема, которая должна требовать другого вопроса. Однако вы создаете временный
std::string
объект, который немедленно уничтожается, что означает, что возвращаемый вами указатель немедленно становится недействительным.5. @SiddharthSingh Чтобы расширить проблему, на которую указал Джеспер Юл, вместо того, чтобы хранить указатели как члены в объекте, создайте полную строку в конструкторе и сохраните ее (как
std::string
объект). Поскольку строка хранится в объекте, указатели на нее (и содержащуюся в ней необработанную строку) будут действительны на протяжении всего срока службы объекта исключения.