从代码的特定部分抛出的异常没有被捕获

时间:2013-04-21 16:19:20

标签: c++ exception-handling

我刚刚为我的OpenGL + GLUT游戏实现了一个基本的异常系统。抛出退出游戏的异常处理得很好,以及其他一些断言异常,但后来我尝试通过删除图像文件夹导致图像加载失败,并且该特定异常似乎没有被捕获。它会导致应用程序关闭,并显示消息“此应用程序请求运行时以不寻常的方式终止”。

这是处理所有异常的try / catch块,它是应用程序类的内联静态方法(它位于头文件中,因为它是模板函数):

#pragma once

#include "logging.hpp"
#include "utils.hpp"
#include "throwables.hpp"
#include <cassert>
#include <exception>

namespace core
{
    class application
    {
    public:
        static const char * const tag;

        template <class T>
        static int run(int argc, char *argv[], const int width, const int height,
            int x, int y, const char * const title) throw (const std::exception &)
        {
            int res = 0;
            logging * const log = logging::get();

            try
            {
                assert(log != NULL);
                log->setverbosity(logging::info);
                dbgcode(log->setverbosity(logging::verbose));

                T * const g = T::get();

                if (!g)
                {
                    log->wtf(tag, "run: g is NULL! are we out of memory?");
                    throw core::assertexception();
                }

                T::envinit(argc, argv);
                g->initialize(width, height, x, y, title);
                g->run();
            }
            catch(const core::exitexception &e)
            {
                // hopefully everything is deallocated properly this way
                log->i(tag, "run: exit message recieved");
                res = 0;
            }
            catch(const core::assertexception &e)
            {
                utils::unexpectederror(title);
                res = 1;
            }
            catch(const core::errorexception &e)
            {
                utils::error(title);
                res = 1;
            }

            log->i(tag, strfmt() << "exiting with code " << res);

            return res;
        }
    };
}

这是抛出永远不会处理的异常的代码(它在g-&gt; run中执行,因此它在try块中):

void sprite::load(const char * const filename) throw (const assertexception &, const errorexception &)
{
    if (!filename) // this exception is handled perfectly
    {
        log->wtf(tag, strfmt() << "load: filename is NULL! what the hell did you pass me?" << img);
            throw assertexception();
    }

    fromtex = false;

    // generate and bind a DevIL image
    ilGenImages(1, &img);
    ilBindImage(img);

    // attempt to load the sprite as a DevIL image
    if (!ilLoadImage(filename)) // this exception is never caught even if I change this to if(true)
    {
        log->e(tag, strfmt() << "load: failed to load " << filename << ", image id = " << img);
        throw errorexception(); // never caught when thrown
    }

    ...

这是我的throwables.hpp / throwables.cpp,我定义了所有自定义异常:

HPP:

#pragma once

#include <stdexcept>
#include <string>

namespace core
{
    class exception : public std::runtime_error
    {
    public:
        exception(const std::string &info);
    };

    class assertexception : public exception
    {
    public:
        assertexception();
    };

    class errorexception : public exception
    {
    public:
        errorexception();
    };

    class exitexception : public exception
    {
    public:
        exitexception();
    };
}

CPP:

#include "throwables.hpp"

namespace core
{
    exception::exception(const std::string &info)
        : std::runtime_error(info)
    {}

    // assertexception
    assertexception::assertexception()
        : exception("an assertion has occurred - check the log file")
    {}

    // errorexception
    errorexception::errorexception()
        : exception("an error has occurred - check the log file")
    {}

    // exitexception
    exitexception::exitexception()
        : exception("exit message recieved")
    {}
}

编辑:另外,这里是我调用的那些utils :: *错误函数:

void unexpectederror(const wxString &gamename)
{
    // TODO: make everything unicode friendly
    // TODO: get all strings from xmls for easy localization
    wxSafeShowMessage(gamename + wxT(" - Unexpected error"),
        wxT("An unexpected error has occurred. Please report this bug")
        wxT(" and attach your lastsession.log file"));
}

void error(const wxString &gamename)
{
    wxSafeShowMessage(gamename + wxT(" - Error"),
        wxT("An error has occurred. Please check your lastsession.log")
        wxT(" for more info and check for <error> messages. Please report it if you believe it is a bug"));
}

void error(const wxString &title, const wxString &text)
{
    wxSafeShowMessage(title, text);
}
顺便说一下,

std :: exception正在main中被捕获:

#include "dungeoncrawler.hpp"
#include "application.hpp"

using namespace core;

int main(int argc, char *argv[])
{
    static const char * const tag = ".main";
    static const char * const title = "DungeonCrawler";

    try
    {
        return application::run<dungeoncrawler::game>(argc, argv, 800, 450, -1, -1, title);
    }
    catch(const std::exception &e)
    {
        utils::unhandledexception(title, e);
        logging::get()->wtf(tag, "unhandled exception, exiting with code 0");
        return 0;
    }

    assert(false); // this code should never be reached
    logging::get()->wtf(tag, "what?! this code should be unreachable! exiting with code 0");
    utils::error(wxString(title), wxT("Unexpected behaviour occurred. Please report this bug to the developer"));

    return 0;
}

1 个答案:

答案 0 :(得分:2)

问题在于如何声明此函数。

void sprite::load(const char * const filename) throw (const assertexception &, const errorexception &)

该函数承诺只抛出异常assertexceptionerrorexception

如果从该函数抛出任何其他异常,将调用std::unexpected()并终止您的程序。例如,如果标准库或任何其他库不知道这些异常类throw,就会发生这种情况。

删除throw子句以修复它。

请参阅this Herb Sutter article了解详情。

相关问题