C++ 扩展std::exception类:program-won';t执行适当的catch处理程序

C++ 扩展std::exception类:program-won';t执行适当的catch处理程序,c++,exception,gcc,exception-handling,C++,Exception,Gcc,Exception Handling,我从std::exception派生了一个类: class exc : public std::exception { public: exc(const text::_char *) throw(); exc(const exc &) throw(); virtual ~exc() throw(); text::_char *m_what; }; 我有两个包装函数来抛出我的异常类型: PS:dbg_out指的是std::cout。文本是std::ba

我从std::exception派生了一个类:

class exc : public std::exception
{
public:
    exc(const text::_char *) throw();
    exc(const exc &) throw();
    virtual ~exc() throw();

    text::_char *m_what;
};
我有两个包装函数来抛出我的异常类型:

PS:dbg_out指的是std::cout。文本是std::basic\u string>的后代

我的程序因以下消息而崩溃:

你好,世界!
此应用程序已请求运行时以异常方式终止它。
有关更多信息,请联系应用程序的支持团队。
我使用gcc编译器(最新的MinGW版本)

我的程序没有在主函数中输入catch处理程序。它没有调用类exc的复制构造函数。它看起来像是由gcc生成的代码,没有将exc识别为std::exception的后代


我做错了什么?

我敢打赌你的问题出在这条线上:

throw exc((const text::_char *)l_message);
您提到的
文本
源自
基本字符串
。不支持从
basic\u string
const char*
的强制转换。因此,除非您在派生类中提供自己的转换运算符,否则在这里您将进入未定义/未指定的行为。尝试将上面的行更改为:

throw exc(l_message.c_str());

这是我在12月5日写的:

exc构造函数复制的内存在复制之前已被删除。访问违规保证!关于这种奇妙的编程语言,我又学到了一件事(当你“抛出exc(一些被删除的内存)”时,幕后会发生什么)

>

这不是真正的问题。真正的问题是gcc编译器(带有选项:)

不希望针对函数声明的“throw()”规范引发异常。当“throw\u exception()”声明为

    void throw_exception() throw(const std::exception &);
一切都很好

我一直认为(至少是软件)异常可能发生在每个调用语句中,堆栈展开过程必须能够处理这一点。我不喜欢这样的想法,即我必须为我编写的每个函数指定可能留下函数的异常类型

不知何故,我应该能够指定任何类型的软件异常都可以在gcc的命令行上留下我编写的任何函数。但是如何做到呢?我将针对这个新主题发布一个新问题


感谢所有为我考虑过的人。

你在调试器下运行过它吗?不要使用va列表,它很可怕而且不安全。改用可变模板。我认为不使用
va\U end
结束可变函数是未定义的行为。
text
std::basic\u string
的后代,
v是什么lb
?类?名称空间?没有足够的信息来回答这个问题,我的猜测是“text”不能转换为“const text::_char*”,C cast强制执行“reinterpret_cast”并导致问题。您需要定义什么是“text”我有一个运算符const text::_char*,这就是原因(call basic_string::c_str())。我找到了答案。构造函数在它复制的内存被删除后被调用。在构造exc对象之前,l_消息早就消失了(l_消息是一个局部变量)-1
l_消息
抛出时超出范围,因此
c_str()
返回的指针将是垃圾。@bert jan:“我有一个操作符const text::_char*…”-写
(const text::_char*)l_message
而不是
l_message.c_str()
?:)@ildjarn不是很好吗?异常类应该创建一个副本,所以没有问题(除非派生类构造函数没有正确实现)@visitor:问题中的
exc
的定义没有复制赋值运算符,这意味着它可能只存储给定的指针(即,如果对象拥有字符串,则三的规则没有实现)。在任何情况下,您都正确地认为异常类应该进行深度复制,因此-1被删除。您还需要了解一件事-没有任何保证。当您进入未定义行为的领域时,任何事情都可能发生,从崩溃到出现工作,再到恶魔从您鼻子里飞出来。您应该发布自己的答案,而不是发布自己的答案编辑更多相关代码,并让人们向您展示(例如,您的
exc
的构造函数).Class
exc
似乎特别可疑。通常,您会从一个标准异常类继承,该类的构造函数采用
const std::string&
,并且构造函数的实现看起来像:
exc::exc(const std::string&msg):std::runtime_error(msg){}
。不要为异常规范操心(如果您想确保没有异常离开函数,可能除了
throw()
)-看起来您仍然从未定义的行为中得到不同的结果:
void throw\u exception();
表示允许函数抛出任何异常。
void throw\u exception()throw(std::exception);
表示只允许这些异常离开函数,否则程序将终止(在给您机会纠正这种情况后)。不知道const引用在异常说明符中可能会产生什么影响。
throw exc(l_message.c_str());
    gcc -fexceptions -Wnoexcept -fno-use-cxa-get-exception-ptr -include .\pch.h -g3 *.cpp 
    -l libstdc++ -o vlb.exe
    void throw_exception() throw(const std::exception &);