Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 应用程序在引发异常时崩溃_C++_Exception - Fatal编程技术网

C++ 应用程序在引发异常时崩溃

C++ 应用程序在引发异常时崩溃,c++,exception,C++,Exception,在我编写的应用程序中,我将异常用于大多数错误处理。我还没有定义自己的异常类,我只是做了以下工作: namespace Mage { typedef std::exception Exception; } 这样,我就不必在以后定义自己的类型时更改所有代码,而该类型应该使用相同的接口 也就是说,任何异常都会使我的应用程序崩溃。考虑到上述定义,为什么会崩溃 void Mage::Root::initialize(Mage::String& p_log) { // initia

在我编写的应用程序中,我将异常用于大多数错误处理。我还没有定义自己的异常类,我只是做了以下工作:

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;
无论我删除还是保留“新”,它都会崩溃。我错过什么了吗?我查阅了一些教程,但这些并没有让我变得更聪明

我在这里也发现了错误:

try {
    MAGE_ROOT.initialize(Mage::String("Mage.log"));
} catch (Mage::Exception& e) {
    std::cerr << e.what() << std::endl;
}

根据错误消息,您正在使用Visual Studio(2010)进行项目。除非你把你的投掷在一个尝试/ catch块,它将“航行通过屋顶”,并“处理”的C++运行时,这意味着调用中止()。在调用堆栈中,您可能需要这样的内容:

try
{
   SomeFunctionThatUltimatelyThrows();
}
catch(Exception & e)
{
   // .. handle error - log, resume, exit, whatever
}
还请注意Scott Meyers关于始终通过引用捕获异常的建议。“异常”:如果您使用的是MFC CEExceptions,那么您希望通过指针捕获并调用Delete方法来自毁基于堆的异常


根据您的编辑,您可能在“按指针”抛出和“按引用”捕获之间存在不匹配。如果您已经解决了这个问题,但仍然无法执行catch块,那么可以尝试通过使用CRT SetAbortHandler安装自己的abort函数来调试abort()调用。这可以简单地链接到现有的调用堆栈中,但可以设置断点并检查调用堆栈以查看出现了什么问题。

根据错误消息,您正在使用Visual Studio(2010)进行项目。除非你把你的投掷在一个尝试/ catch块,它将“航行通过屋顶”,并“处理”的C++运行时,这意味着调用中止()。在调用堆栈中,您可能需要这样的内容:

try
{
   SomeFunctionThatUltimatelyThrows();
}
catch(Exception & e)
{
   // .. handle error - log, resume, exit, whatever
}
还请注意Scott Meyers关于始终通过引用捕获异常的建议。“异常”:如果您使用的是MFC CEExceptions,那么您希望通过指针捕获并调用Delete方法来自毁基于堆的异常


根据您的编辑,您可能在“按指针”抛出和“按引用”捕获之间存在不匹配。如果您已经解决了这个问题,但仍然无法执行catch块,那么可以尝试通过使用CRT SetAbortHandler安装自己的abort函数来调试abort()调用。这可以简单地链接到现有的调用堆栈中,但可以设置断点并检查调用堆栈,以查看出现了什么问题。

问题在于您没有捕获异常


我不知道你必须抓住例外(从评论中)

是的,你必须这样做。如果未捕获抛出的异常,将调用
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()
。这是预期的行为:存在异常是为了防止程序员忘记错误处理

尽管如此,我建议:

  • 按价值抛掷
  • 参照捕捉
例如:

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...
    }
}

如果您发布的代码确实是您正在使用的代码,您将看到控制权被转移到您的处理程序。

C++尝试为假人使用catch-throw逻辑。请注意,这不包括基于RAII/堆栈的分配/销毁

  • 当您抛出异常时,异常被称为“正在传播”。它向上传播调用堆栈,直到找到可以处理它的第一个处理程序(因此它被捕获),或者直到它到达调用堆栈的根。
    • 如果捕获到异常,则从捕获异常的点继续执行。异常在catch块的末尾被销毁
    • 如果找到根,则调用std::unhandled_exception,它通常调用std::terminate,它通常调用abort()。简言之,一切都会尽快结束
  • 如果在异常当前传播时引发异常,则一次将有两个异常传播。Java和C#有着巧妙的处理方法,但这一点从一开始就不应该发生——没有异常处理程序能够在逻辑上处理异常组合。当前正在传播时不要抛出异常。即使不使用不应该使用的std::uncaught_exception(),这个规则也不难保持
  • 在展开堆栈/传播异常时,堆栈上找到的所有对象都将被销毁。这些析构函数永远不应该抛出异常——毕竟,当销毁对象“失败”时,在析构函数修复它之后,您还打算做什么
  • 始终按值抛出,按引用捕获。如果您通过指针抛出和捕获,您很可能会泄漏某些内容,而引用是不可能的。如果您按值捕获,则将切掉派生的异常类型。参照捕获
  • 在软件的根目录中,包含一个catch all-
    catch(…)
    。这不允许你知道你到底抓到了什么,但至少你可以安全地撞车。当被调用的代码可能抛出您不知道的“某物”时,也要这样做

C++为假人尝试捕捉抛出逻辑。请注意,这不包括基于RAII/堆栈的分配/销毁

  • 当您抛出异常时,异常被称为“正在传播”。它向上传播