在我写的应用程序中,我使用异常来处理大部分错误。我还没有定义自己的异常类,我只做了以下几点:
namespace Mage {
typedef std::exception Exception;
}
这样,当我稍后定义自己的类型时,我将不必更改所有代码,这应该使用相同的接口。
也就是说,任何异常都会导致我的应用程序崩溃。考虑到上面的定义,为什么会崩溃?
void Mage::Root::initialize(Mage::String& p_log) {
// initialize GLFW and GLEW.
if (!glfwInit()) {
throw new Mage::Exception("failed to initialize OpenGL");
return;
} else m_GLFWInitialized = true;
无论我删除还是保留'new',它都会崩溃。我错过了什么吗?我已经查阅了教程,但那些并没有让我更聪明。
我也在这里发现错误:
try {
MAGE_ROOT.initialize(Mage::String("Mage.log"));
} catch (Mage::Exception& e) {
std::cerr << e.what() << std::endl;
}
我得到的崩溃是:
Debug Error!
Program: ...sual Studio 2010\Project\Mage3D\Binaries\Debug\Test.exe
R6010
- abort() has been called
(Press Retry to debug application)
答案 0 :(得分:11)
问题是你没有发现你的异常。
我不知道你 - 有 - 抓住异常(来自评论)
是的,你必须这样做。如果您没有捕获抛出异常,将调用std::terminate()
。这是预期的行为:存在例外以防止程序员忘记关于错误处理。
这说,我建议:
例如:
void foo()
{
// ...
throw std::logic_error("Error!");
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Throw by value (std::logic_error derives from std::exception)
// ...
}
void bar()
{
try
{
// ...
foo();
// ...
}
catch (std::exception& e)
^^^^^^^^^^^^^^^
// Catch by reference
{
std::cout << e.what(); // For instance...
}
}
<强>更新强>
关于您发布的代码段,您正在抛出指针并通过引用捕获。处理程序不匹配。由于没有其他匹配处理程序,因此将调用std::terminate()
。
相反,您应该按值抛出异常:
throw Mage::Exception("failed to initialize OpenGL");
如果您发布的代码确实是您正在使用的代码,您将看到该控件已转移到您的处理程序。
答案 1 :(得分:2)
根据错误消息,您正在为项目使用Visual Studio(2010)。除非你将throw包装在try / catch块中,否则它将“通过屋顶”并由C ++运行时“处理”,这意味着调用abort()。您可能希望调用堆栈中的内容更高:
try
{
SomeFunctionThatUltimatelyThrows();
}
catch(Exception & e)
{
// .. handle error - log, resume, exit, whatever
}
另请注意,Scott Meyers建议始终通过引用捕获异常。 “异常”:如果您正在使用MFC CExceptions,您希望通过指针捕获并调用Delete方法来自毁基于堆的异常。
根据您的编辑,您可能在投掷“按指针”和捕获“按引用”之间不匹配。如果您已经解决了这个问题并且仍未执行catch块,则可以尝试使用CRT SetAbortHandler来调试abort()调用以安装您自己的中止函数。这可以简单地链接到现有的一个,但是可以设置一个断点并检查调用堆栈以查看出错的地方。
答案 2 :(得分:1)
C ++ try-catch-throw逻辑用于假人。请注意,这不包括基于RAII /堆栈的分配/销毁。
catch(...)
。这不允许你找出你到底抓到了什么,但至少你可以安全地坠毁。当被调用的代码可能抛出你不知道的“东西”时,也要这样做。