我刚刚为我的 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->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,我在其中定义了所有自定义异常:
惠普:
#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();
};
}
cp:
#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::*error 函数:
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;
}