0

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();
    };
}

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::*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 はメインでキャッチされています:

#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;
}
4

1 に答える 1