A robust and thread-safe exception handling library for C, inspired by modern programming languages. This library provides try, catch, and throw macros for structured error handling in both single-threaded and multi-threaded applications.
- Structured Exception Handling: Familiar
try,catch, andthrowconstructs. - Thread Safety: Isolates exceptions across threads with thread-local storage.
- Custom Messages: Supports
printf-style formatted messages for exceptions. - Nested Exception Propagation: Handle exceptions across function call levels.
- Integrated with Modern Tools: Leverages
.clang-formatand.clangdfor code consistency and tooling.
.
βββ CMakeLists.txt # Main CMake configuration
βββ include/
β βββ exception.h # Library header
βββ README.md # Project documentation
βββ src/
β βββ exception.c # Library source
βββ tests/
βββ CMakeLists.txt # CMake configuration for tests
βββ exception_tests.c # Unit tests for the library- CMake (version 3.15 or newer)
- GCC/Clang (with C11 support)
- CMocka (optional, for testing)
-
Clone the Repository:
git clone https://github.com/mrpriv4te/exception-c.git cd exception-c -
Create a Build Directory:
mkdir build && cd build
-
Configure the Project:
cmake ..
-
Build the Library:
cmake --build .
-
Enable Testing During Configuration:
cmake -DBUILD_TESTING=ON ..
-
Build and Execute the Tests:
cmake --build . && ctest
-
Install the Library (from the build directory):
cmake --install . -
Update Your Projectβs
CMakeLists.txt:cmake_minimum_required(VERSION 3.15) project(YourProject LANGUAGES C) # Find and link the exception library find_package(ExceptionLibrary CONFIG REQUIRED) add_executable(your_project main.c) target_link_libraries(your_project PRIVATE exception) target_include_directories(your_project PRIVATE ${CMAKE_INSTALL_PREFIX}/include)
-
Copy the
src/andinclude/Directories into your project directory. -
Update Your Projectβs
CMakeLists.txt:cmake_minimum_required(VERSION 3.15) project(YourProject LANGUAGES C) # Add the exception library add_library(exception path/to/src/exception.c) target_include_directories(exception PUBLIC path/to/include) add_executable(your_project main.c) target_link_libraries(your_project PRIVATE exception)
-
Add the Submodule:
git submodule add https://github.com/mrpriv4te/exception-c.git libs/exception
-
Update Your Projectβs
CMakeLists.txt:cmake_minimum_required(VERSION 3.15) project(YourProject LANGUAGES C) # Add the exception library as a subdirectory add_subdirectory(libs/exception) add_executable(your_project main.c) target_link_libraries(your_project PRIVATE exception)
#include "exception.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
try({
throw(1, "An error occurred: %s", "example message");
} catch(1) {
printf("Caught exception: %s\n", exception()->message);
})
try({
int rand_exception_code = rand();
throw(rand_exception_code, "An other error occurred: %s", "example message");
} catch(all_exception) {
printf("Caught exception: %s with rand code %d\n", exception()->message, exception()->code);
})
return 0;
}#include "exception.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *thread_function(void *arg) {
int thread_id = *(int *)arg;
try({
if (thread_id % 2 == 0) {
throw(100 + thread_id, "Thread %d exception", thread_id);
}
} catch(100 + thread_id) {
printf("Caught exception in thread %d: %s\n", thread_id, exception()->message);
})
pthread_exit(NULL);
}
int main() {
const int num_threads = 4;
pthread_t threads[num_threads];
int thread_ids[num_threads];
for (int i = 0; i < num_threads; i++) {
thread_ids[i] = i;
pthread_create(&threads[i], NULL, thread_function, &thread_ids[i]);
}
for (int i = 0; i < num_threads; i++) {
pthread_join(threads[i], NULL);
}
return 0;
}The project includes unit tests written with CMocka that validate:
- Basic exception handling
- Nested function call propagation
- Multithreading with caught and uncaught exceptions
- Thread safety across multiple scenarios
-
Enable Testing in CMake:
cmake -DBUILD_TESTING=ON ..
-
Build and Execute Tests:
cmake --build . && ctest -V
Example output:
...
test 1
Start 1: ExceptionTests
1: Test command: /path/to/exception-c/build/tests/exception_tests
1: Working Directory: /path/to/exception-c/build/tests
1: Test timeout computed to be: 10000000
1: [==========] tests: Running 7 test(s).
1: [ RUN ] test_throw_and_catch
1: [ OK ] test_throw_and_catch
1: [ RUN ] test_throw_uncaught
1: exception_tests: /path/to/exception-c/tests/exception_tests.c:41: test_throw_uncaught(): Uncaught exception (code 2)
1: [ OK ] test_throw_uncaught
1: [ RUN ] test_message_update
1: [ OK ] test_message_update
1: [ RUN ] test_nested_function_call
1: [ OK ] test_nested_function_call
1: [ RUN ] test_multithreaded_exceptions
1: [ OK ] test_multithreaded_exceptions
1: [ RUN ] test_multithreaded_exceptions_uncaught
1: exception_tests: Thread 126242628044480: /path/to/exception-c/tests/exception_tests.c:130: thread_function_uncaught(): Thread 0 uncaught exception (code 50)
1: exception_tests: Thread 126242649016000: /path/to/exception-c/tests/exception_tests.c:130: thread_function_uncaught(): Thread 2 uncaught exception (code 52)
1: [ OK ] test_multithreaded_exceptions_uncaught
1: [ RUN ] test_thread_safety
1: [ OK ] test_thread_safety
1: [==========] tests: 7 test(s) run.
1: [ PASSED ] 7 test(s).
1/1 Test #1: ExceptionTests ................... Passed 0.00 sec
100% tests passed, 0 tests failed out of 1
Total Test time (real) = 0.01 sec
- .clang-format: Ensures consistent code style across the project. Based on LLVM style.
- .clangd: Provides IDE tooling for code navigation, autocompletion, and diagnostics.
To format the source files:
clang-format -i src/*.c include/*.hContributions are welcome! To get started:
-
Fork the Repository:
git fork https://github.com/mrpriv4te/exception-c.git
-
Create a Branch:
git checkout -b feature/your-feature
-
Commit Your Changes:
git commit -m "Add your feature" -
Push the Branch:
git push origin feature/your-feature
-
Submit a Pull Request.
This project is licensed under the MIT License.
- Inspired by exception handling mechanisms in C++ and Python.
- Built with thread safety and modern C practices in mind.
Happy coding! π