A lightweight, header-only C99 exception library — thread-safe, cross-platform, no heap usage, fully nestable and customizable.
- 🚀 Header-only: Single file inclusion
- 🧵 Thread-safe: Built-in thread-local storage support
- 🌐 Cross-platform: Works on Windows, Linux, macOS, and other platforms
- 💾 Zero heap allocation: Uses stack-based exception frames
- 🔄 Fully nestable: Support for nested try-catch blocks
- ⚙️ Customizable: Configurable features and exception handlers
- 📝 C99 compliant: Works with standard C99 compilers
#define XCEP_IMPLEMENTATION
#include "XCEP.h"
#include <stdio.h>
int main() {
Try {
printf("About to throw an exception\n");
Throw(42, "Something went wrong");
printf("This won't be printed\n");
}
Catch(42) {
printf("Caught exception: %s (code: %d)\n",
CaughtException.message, CaughtException.code);
}
Finally {
printf("Cleanup code here\n");
}
EndTry;
return 0;
}Try {
printf("Outer try block\n");
Try {
printf("Inner try block\n");
Throw(100, "Inner exception");
}
Catch(100) {
printf("Caught in inner: %s\n", CaughtException.message);
Throw(200, "Re-throwing as different exception");
}
EndTry;
}
Catch(200) {
printf("Caught in outer: %s\n", CaughtException.message);
}
EndTry;Try {
Throw(404, "Resource not found");
}
CatchAll {
printf("Exception details:\n");
printf(" Code: %d\n", CaughtException.code);
printf(" Message: %s\n", CaughtException.message);
printf(" Function: %s\n", CaughtException.function);
printf(" File: %s\n", CaughtException.file);
printf(" Line: %d\n", CaughtException.line);
}
EndTry;| Macro | Description |
|---|---|
Try |
Begin a try block |
Catch(code) |
Catch specific exception code |
CatchAll |
Catch any exception |
Finally |
Execute code regardless of exceptions |
EndTry |
End the try-catch block |
Throw(code, message) |
Throws an exception. message must be a C string literal. |
Rethrow |
Re-throw the current exception |
CaughtException.code- Exception error codeCaughtException.message- Exception message stringCaughtException.function- Function where exception was thrownCaughtException.file- Source file where exception was thrownCaughtException.line- Line number where exception was thrown
// Global uncaught exception handler
SetUncaughtExceptionHandler(XCEPTEST_handler);
// Thread-specific uncaught exception handler (if thread-safe mode enabled)
SetThreadUncaughtExceptionHandler(XCEPTEST_thread_handler);// Print formatted exception information
PrintException("Error occurred", &exception);Configure XCEP by editing macros in the header:
// Enable/disable thread safety if not needed (default: 1)
#define XCEP_CONF_ENABLE_THREAD_SAFE 1
// Enable/disable short command names to avoid collision (default: 1)
#define XCEP_CONF_ENABLE_SHORT_COMMANDS 1When XCEP_CONF_ENABLE_THREAD_SAFE is enabled:
- Exception stacks are thread-local
- Each thread maintains its own exception context
- Thread-specific uncaught exception handlers are available
When XCEP_CONF_ENABLE_SHORT_COMMANDS is disabled, use prefixed versions:
XCEP_Tryinstead ofTryXCEP_Catch(code)instead ofCatch(code)XCEP_Throw(code, msg)instead ofThrow(code, msg)- etc.
void XCEPTEST_exception_handler(const XCEP_t_Exception* ex) {
fprintf(stderr, "FATAL: Unhandled exception %d: %s\n",
ex->code, ex->message);
fprintf(stderr, " at %s (%s:%d)\n",
ex->function, ex->file, ex->line);
exit(ex->code);
}
int main() {
SetUncaughtExceptionHandler(XCEPTEST_exception_handler);
// This will trigger the custom handler
Throw(1, "Unhandled exception");
return 0;
}void risky_function() {
Try {
Throw(500, "Database error");
}
Catch(500) {
printf("Handling database error\n");
Rethrow; // Propagate to caller
}
EndTry;
}
int main() {
Try {
risky_function();
}
Catch(500) {
printf("Caught propagated exception: %s\n", CaughtException.message);
}
EndTry;
return 0;
}XCEP automatically detects the compiler and platform to use appropriate thread-local storage:
- MSVC:
__declspec(thread) - GCC/Clang with C11:
_Thread_local - GCC/Clang (older):
__thread - C23:
thread_local
- Calling
Rethrowoutside a catch block will trigger an assertion - Uncaught exceptions will call the registered handler or exit with the exception code
- All exception frames are stack-allocated with no heap usage
Simply copy XCEP.h to your project and:
#define XCEP_IMPLEMENTATION
#include "XCEP.h"The implementation should only be included once in your project.
MIT license, See the included license in XCEP.h for more information.
Note: XCEP uses setjmp/longjmp internally. Be aware of the standard limitations regarding local variables and optimization when using this library. Always use volatile for variables that are modified in blocks and accessed after exceptions. Try