Skip to content

Instantly share code, notes, and snippets.

@royvandam
Last active April 9, 2021 21:44
Show Gist options
  • Save royvandam/bc567629299729dc82f752ff4b43183e to your computer and use it in GitHub Desktop.
Save royvandam/bc567629299729dc82f752ff4b43183e to your computer and use it in GitHub Desktop.
Simple C++ global exception handling for targets with -fno-exceptions enabled
#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