Last active
April 9, 2021 21:44
-
-
Save royvandam/bc567629299729dc82f752ff4b43183e to your computer and use it in GitHub Desktop.
Simple C++ global exception handling for targets with -fno-exceptions enabled
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
class Exception { | |
public: | |
using StringType = const char*; | |
protected: | |
StringType _what; | |
StringType _file; | |
std::size_t _line; | |
StringType _message; | |
public: | |
constexpr Exception(StringType what, StringType file, std::size_t line, char const* message = nullptr) noexcept | |
: _what(what), _file(file), _line(line), _message(message) {} | |
[[nodiscard]] constexpr StringType what() const noexcept { | |
return _what; | |
} | |
[[nodiscard]] constexpr StringType file() const noexcept { | |
return _file; | |
} | |
[[nodiscard]] constexpr std::size_t line() const noexcept { | |
return _line; | |
} | |
[[nodiscard]] constexpr StringType message() const noexcept { | |
return _message; | |
} | |
[[nodiscard]] constexpr StringType format() const noexcept { | |
return ""; | |
} | |
}; | |
class NullptrException : public Exception { | |
public: | |
NullptrException(StringType file, std::size_t line, StringType message = nullptr) : Exception("null pointer", file, line, message) {} | |
}; | |
class RuntimeError : public Exception { | |
public: | |
RuntimeError(StringType file, std::size_t line, StringType message = nullptr) : Exception("runtime error", file, line, message) {} | |
}; | |
class ExceptionHandler { | |
public: | |
using Callback = std::function<void(Exception&& e)>; | |
static void SetCallback(Callback&& fn) { | |
_callback = std::move(fn); | |
} | |
static void Handle(Exception&& e) { | |
if (_callback) { | |
_callback(std::forward<Exception>(e)); | |
} | |
} | |
private: | |
inline static Callback _callback; | |
ExceptionHandler() = delete; | |
}; | |
namespace Detail { | |
inline void Raise(Exception&& e) { | |
ExceptionHandler::Handle(std::forward<Exception>(e)); | |
} | |
} | |
#define Raise(E, ...) Detail::Raise(E(__FILE__, __LINE__, ##__VA_ARGS__)) | |
#include <cstdio> | |
#include <cassert> | |
void SomeFunction(void* someArg) { | |
if (someArg == nullptr) { | |
Raise(NullptrException, "Dude WTF!"); | |
} | |
} | |
int main() { | |
ExceptionHandler::SetCallback([](Exception&& e) { | |
printf("Caught '%s' exception @ %s:%lu\n", e.what(), e.file(), e.line()); | |
if (e.message() != nullptr) { | |
printf(" message: %s\n", e.message()); | |
} | |
// Panic \0/ | |
assert(true); // || halt(); || reboot(); | |
}); | |
SomeFunction(nullptr); | |
return 0; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment