Initial commit
This commit is contained in:
		
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| MIT License | ||||
|  | ||||
| Copyright (c) [year] [fullname] | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in all | ||||
| copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| SOFTWARE. | ||||
							
								
								
									
										76
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| # Compiler Flags | ||||
| CC := gcc | ||||
| CFLAGS := -g -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined -fno-omit-frame-pointer | ||||
| export ASAN_OPTIONS = allocator_may_return_null=1 | ||||
| # Directory variables  | ||||
| LIBDIR := lib | ||||
| OBJ := obj | ||||
| INC := include | ||||
| SRC := src | ||||
| TEST := tests | ||||
|  | ||||
| # Filepath Pattern Matching | ||||
| LIB := $(LIBDIR)/lib.a | ||||
| SRCS := $(wildcard $(SRC)/*.c) | ||||
| OBJS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(SRCS)) | ||||
| TESTS := $(wildcard $(TEST)/*.c) | ||||
| TESTBINS := $(patsubst $(TEST)/%.c, $(TEST)/bin/%, $(TESTS)) | ||||
|  | ||||
| # Commands must be labeled PHONY | ||||
| .PHONY: all release clean test | ||||
|  | ||||
| # Compiler Release Flags  | ||||
| release: CFLAGS := -Wall -Wextra -Werror -pedantic -fsanitize=address,undefined -fno-omit-frame-pointer -O2 -DNDEBUG | ||||
| release: clean $(LIB) | ||||
|  | ||||
| # Target for compilation. | ||||
| all: $(LIB) | ||||
|  | ||||
| # Target / Dependencies | ||||
| $(LIB): $(OBJS) | $(LIBDIR) | ||||
| 	$(RM) $(LIB) | ||||
| 	ar -cvrs $@ $^ | ||||
|  | ||||
| $(OBJ)/%.o: $(SRC)/%.c $(SRC)/%.h | $(OBJ) | ||||
| 	$(CC) $(CFLAGS) -c $< -o $@ | ||||
|  | ||||
| $(OBJ)/%.o: $(SRC)/%.c | $(OBJ) | ||||
| 	$(CC) $(CFLAGS) -c $< -o $@ | ||||
|  | ||||
| $(TEST)/bin/%: $(TEST)/%.c $(LIB) | $(TEST)/bin | ||||
| 	$(CC) $(CFLAGS) $< $(LIB) -o $@ | ||||
|  | ||||
| # Make directories if none.  | ||||
| $(LIBDIR): | ||||
| 	mkdir $@ | ||||
|  | ||||
| $(INC): | ||||
| 	mkdir $@ | ||||
|  | ||||
| $(OBJ): | ||||
| 	mkdir $@ | ||||
|  | ||||
| $(TEST)/bin: | ||||
| 	mkdir $@ | ||||
|  | ||||
| # Run the tests in the bin folder and track results | ||||
| test: $(LIB) $(TEST)/bin $(TESTBINS) | ||||
| 	@SUCCESS_COUNT=0; FAILURE_COUNT=0; \ | ||||
| 	for test in $(TESTBINS); do \ | ||||
| 		./$$test; \ | ||||
| 		EXIT_CODE=$$?; \ | ||||
| 		TEST_NAME=$(notdir $$test); \ | ||||
| 		if [ $$EXIT_CODE -eq 0 ]; then \ | ||||
| 			echo "\033[0;32m$$TEST_NAME: EXIT CODE: $$EXIT_CODE (SUCCESS)\033[0m"; \ | ||||
| 			SUCCESS_COUNT=$$((SUCCESS_COUNT + 1)); \ | ||||
| 		else \ | ||||
| 			echo "\033[0;31m$$TEST_NAME: EXIT CODE: $$EXIT_CODE (FAILURE)\033[0m"; \ | ||||
| 			FAILURE_COUNT=$$((FAILURE_COUNT + 1)); \ | ||||
| 		fi; \ | ||||
| 	done; \ | ||||
| 	echo "\n\nTests completed"; \ | ||||
| 	echo "SUCCESS: $$SUCCESS_COUNT"; \ | ||||
| 	echo "FAILURE: $$FAILURE_COUNT"; | ||||
|  | ||||
| clean: | ||||
| 	$(RM) -r $(LIBDIR) $(OBJ) $(TEST)/bin/ | ||||
							
								
								
									
										23
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # arena  | ||||
|  | ||||
| ## Description | ||||
| Arena based memory allocation. | ||||
|  | ||||
| ## Table of Contents | ||||
|  | ||||
| - [Description](#description) | ||||
| - [Features](#features)  | ||||
| - [Usage](#usage) | ||||
| - [Credits / Resources](#credits--resources) | ||||
| - [License](#license) | ||||
|  | ||||
| ## Features / TODOS | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| ## Credits / Resources | ||||
| [C Interfaces and Implementations - David Hanson](https://github.com/drh/cii)<br> | ||||
| [Arena Allocator Tips and Tricks - Chris Wellons](https://nullprogram.com/blog/2023/09/27/)<br> | ||||
| [Memory Allocation Strategies - Ginger Bill](https://www.gingerbill.org/series/memory-allocation-strategies/)<br> | ||||
| ## License | ||||
| This project is licensed under MIT - see the [LICENSE](LICENSE) file for details. | ||||
							
								
								
									
										20
									
								
								include/arena.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/arena.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| #ifndef ARENA_INCLUDED | ||||
| #define ARENA_INCLUDED | ||||
|  | ||||
| struct Arena { | ||||
|     unsigned char *beg; | ||||
|     unsigned char *end; | ||||
| }; | ||||
| typedef struct Arena Arena; | ||||
|  | ||||
| extern void *arena_alloc(int flags, struct Arena *a, size_t nbytes,  | ||||
|         size_t align, size_t count, const char *file, int line); | ||||
|  | ||||
| extern struct Arena arena_new(int flags, size_t cap, const char *file, int line); | ||||
| extern void arena_back(struct Arena *a, void *buf, size_t len); | ||||
|  | ||||
| #define ARENA(flags, cap) arena_new((flags), (cap), __FILE__, __LINE__) | ||||
| #define ARENA_BACK(a, buf, len) arena_back((a), (buf), (len)) | ||||
| #define ARENA_ALLOC(flags, a, nbytes, align, count) \ | ||||
|     arena_alloc((flags), (a), (nbytes), (align), (count), __FILE__, __LINE__) | ||||
| #endif | ||||
							
								
								
									
										81
									
								
								include/except.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								include/except.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| #ifndef EXCEPT_INCLUDED | ||||
| #define EXCEPT_INCLUDED | ||||
|  | ||||
| #include <setjmp.h> | ||||
| #define UNUSED(x) (void)(x) | ||||
|  | ||||
| struct Exception { | ||||
| 	const char *reason; | ||||
| }; | ||||
| typedef struct Exception Exception; | ||||
|  | ||||
| struct ExceptFrame { | ||||
| 	struct ExceptFrame *prev;   // Exception Stack | ||||
| 	jmp_buf env;                // Enviroment Buffer | ||||
|     	const char *file;           // Exception File | ||||
| 	int line;                   // Exception Line | ||||
| 	const Exception *exception; // Exception Reason | ||||
| }; | ||||
| typedef struct ExceptFrame ExceptFrame; | ||||
|  | ||||
| // Exception States  | ||||
| enum { EXCEPT_ENTERED=0, EXCEPT_RAISED, EXCEPT_HANDLED, EXCEPT_FINALIZED}; | ||||
|  | ||||
| void except_raise(const Exception *e, const char *file,int line); // Raise exceptions | ||||
|  | ||||
| // External declarations  | ||||
| extern ExceptFrame *except_stack; // Global exception stack | ||||
| extern const Exception assert_failed; // Forward declaration for assert.  | ||||
| extern void asserted(int e); | ||||
|  | ||||
| #ifdef NDEBUG | ||||
| #define ASSERTED(e) ((void)0) | ||||
| #else | ||||
| #define ASSERTED(e) ((void)((e)||(RAISE(assert_failed),0))) | ||||
| #endif | ||||
|  | ||||
| // Raise an Exception. | ||||
| #define RAISE(e) except_raise(&(e), __FILE__, __LINE__) | ||||
|  | ||||
| // Reraise the currect exception. | ||||
| #define RERAISE except_raise(except_frame.exception, \ | ||||
| 	except_frame.file, except_frame.line) | ||||
|  | ||||
| // Switch to the previous exception frame and return. | ||||
| #define RETURN switch (except_stack = except_stack->prev,0) default: return | ||||
|  | ||||
| // Start a try block. | ||||
| #define TRY do { \ | ||||
| 	volatile int except_flag; \ | ||||
| 	ExceptFrame except_frame; \ | ||||
| 	except_frame.prev = except_stack; \ | ||||
| 	except_stack = &except_frame;  \ | ||||
| 	except_flag = setjmp(except_frame.env); \ | ||||
| 	if (except_flag == EXCEPT_ENTERED) { | ||||
|  | ||||
| // Handle specific example. | ||||
| #define EXCEPT(e) \ | ||||
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||
| 	} else if (except_frame.exception == &(e)) { \ | ||||
| 		except_flag = EXCEPT_HANDLED; | ||||
|  | ||||
| // Catch all other exceptions.         | ||||
| #define ELSE \ | ||||
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||
| 	} else { \ | ||||
| 		except_flag = EXCEPT_HANDLED; | ||||
|  | ||||
| // Execute finalization code.         | ||||
| #define FINALLY \ | ||||
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||
| 	} { \ | ||||
| 		if (except_flag == EXCEPT_ENTERED) \ | ||||
| 			except_flag = EXCEPT_FINALIZED; | ||||
|  | ||||
| // End Try block.          | ||||
| #define END_TRY \ | ||||
| 		if (except_flag == EXCEPT_ENTERED) except_stack = except_stack->prev; \ | ||||
| 		} if (except_flag == EXCEPT_RAISED) RERAISE; \ | ||||
| } while (0) | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										35
									
								
								include/mem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								include/mem.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| #ifndef MEM_INCLUDED | ||||
| #define MEM_INCLUDED | ||||
|  | ||||
| #include "except.h" // Exceptions | ||||
| #include <stddef.h> // size_t | ||||
|  | ||||
| /* General Macros*/ | ||||
| #define MEM_KB(x) ((size_t)(x) * 1024ULL) | ||||
| #define MEM_MB(x) ((size_t)(x) * 1024ULL * 1024ULL) | ||||
| #define MEM_GB(x) ((size_t)(x) * 1024ULL * 1024ULL * 1024ULL) | ||||
| #define MEM_SIZE(x)    (ptrdiff_t)sizeof(x) | ||||
| #define MEM_COUNT(a)   (MEM_SIZE(a) / MEM_SIZE(*(a))) | ||||
| #define MEM_LEN(s)     (MEM_COUNT(s) - 1) | ||||
|  | ||||
| /* Default behavior is to throw exceptions and zero out memory*/ | ||||
| enum MemFlags { | ||||
|     NOZERO       = 1 << 0,  /* 0001 */ | ||||
|     SOFT_FAIL    = 1 << 1,  /* 0010 */ | ||||
|     HARD_FAIL    = 1 << 2,  /* 0100 */ | ||||
| }; | ||||
|  | ||||
| extern const Exception OOM; // Out of memory | ||||
|  | ||||
| extern void *mem_alloc (int flags, size_t nbytes, const char *file, int line); | ||||
| extern void mem_free(void *ptr, const char *file, int line); | ||||
| extern void *mem_resize(int flags, void *ptr, size_t nbytes, const char *file, int line); | ||||
| extern int mem_is_zero(const void *ptr, size_t nbytes); | ||||
|  | ||||
|  | ||||
| #define ALLOC(flags, nbytes)  mem_alloc((flags), (nbytes), __FILE__, __LINE__) | ||||
| #define FREE(ptr) ((void)(mem_free((ptr), __FILE__, __LINE__), (ptr) = 0)) | ||||
| #define RESIZE(flags, ptr, nbytes) 	((ptr) = mem_resize((flags), (ptr), \ | ||||
| 	(nbytes), __FILE__, __LINE__)) | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										38
									
								
								src/arena.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/arena.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| #include "../include/mem.h"   // Flags | ||||
| #include "../include/arena.h" // Arena | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| struct Arena arena_new(int flags, size_t cap, const char *file, int line){ | ||||
|     struct Arena a = {0}; | ||||
|     a.beg = mem_alloc(flags, cap, file, line); | ||||
|     a.end = a.beg ? a.beg+cap : 0; | ||||
|     return a; | ||||
| } | ||||
| void arena_back(struct Arena *a, void *buf, size_t len){ | ||||
|     ASSERTED(a != NULL); | ||||
|     ASSERTED(buf != NULL); | ||||
|     ASSERTED(len > 0); | ||||
|     a->beg = (unsigned char *)buf; | ||||
|     a->end = a->beg+len; | ||||
| } | ||||
| void *arena_alloc(int flags, struct Arena *a, size_t nbytes, size_t align,  | ||||
|         size_t count, const char *file, int line){ | ||||
|     ptrdiff_t padding = -(uintptr_t)a->beg & (align - 1); | ||||
|     ptrdiff_t available = a->end - a->beg - padding; | ||||
|     if (available < 0 || count > available/nbytes) { | ||||
|         if(flags & SOFT_FAIL) return NULL; | ||||
|         if(flags & HARD_FAIL) exit(12); // ENOMEM | ||||
|         // Raise Exception  | ||||
|         if (file == NULL) // Wasn't called by macro | ||||
|             RAISE(OOM); // Out of Memory Exception | ||||
|         else // Called by macro | ||||
|             except_raise(&OOM, file, line); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     void *p = a->beg + padding; | ||||
|     a->beg += padding + count*nbytes; | ||||
|     // Check flags to see if it gets zeroed out | ||||
|     return flags&NOZERO ? p : memset(p, 0, count*nbytes); | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/except.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/except.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| #include "../include/except.h" | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| ExceptFrame *except_stack = NULL; // Global exception stack. | ||||
| const Exception assert_failed = { "Assertion Failure!" }; // If ASSERT fails. | ||||
|  | ||||
| void except_raise(const Exception *e, const char *file,int line) { | ||||
|     // An exception was raised, grab the exception stack. | ||||
| 	ExceptFrame *p = except_stack; | ||||
|     asserted(e != NULL);  // Ensure exception pointer is not NULL | ||||
| 	if (p == NULL) { // Uncaught Exception | ||||
|         const char *msg = e->reason ? e->reason : "Uncaught Exception!";  | ||||
| 		fprintf(stderr,"\033[31m%s | Address: 0x%p | Raised at %s@%d \033[0m" ,msg,(void *)e,file,line); | ||||
|         fflush(stderr); | ||||
|         abort(); | ||||
|     } | ||||
|    // Set the exception details to the current frame.  | ||||
| 	p->exception = e; // Exception reason | ||||
| 	p->file = file; | ||||
| 	p->line = line; | ||||
|     // Move to the previous frame in the stack. | ||||
| 	except_stack = except_stack->prev; | ||||
|     // Jump to the saved context environment. | ||||
| 	longjmp(p->env, EXCEPT_RAISED); | ||||
| } | ||||
| void asserted(int e) { | ||||
| 	ASSERTED(e); | ||||
|     UNUSED(e); | ||||
| } | ||||
							
								
								
									
										65
									
								
								src/mem.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/mem.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include "../include/except.h" | ||||
| #include "../include/mem.h" | ||||
|  | ||||
| const Exception OOM = { "Out of Memory" };/* Out of memory Exception */ | ||||
| #define MEM_ENOMEM 12 /* Out of memory errno */ | ||||
|  | ||||
| void *mem_alloc(int flags, size_t nbytes, const char *file, int line){ | ||||
|     void *ptr; | ||||
|     ASSERTED(nbytes > 0); | ||||
|     ptr = malloc(nbytes); | ||||
|     if (ptr == NULL){ | ||||
|         if (flags & SOFT_FAIL) return 0; | ||||
|         if (flags & HARD_FAIL) exit(MEM_ENOMEM); | ||||
|  | ||||
|         if (file == NULL) // Wasn't called by macro | ||||
|             RAISE(OOM); // Out of Memory Exception | ||||
|         else // Called by macro | ||||
|             except_raise(&OOM, file, line); | ||||
|     } | ||||
|     return flags&NOZERO ? ptr : memset(ptr, 0, nbytes); | ||||
| } | ||||
|  | ||||
| void mem_free(void *ptr, const char *file, int line) { | ||||
|     UNUSED(file); | ||||
|     UNUSED(line); | ||||
|     if (ptr){ | ||||
|         free(ptr); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void *mem_resize(int flags, void *ptr, size_t nbytes,const char *file, int line) { | ||||
|     ASSERTED(ptr); | ||||
|     ASSERTED(nbytes > 0); | ||||
|     ptr = realloc(ptr, nbytes); | ||||
|     if (ptr == NULL){ | ||||
|         if(flags & SOFT_FAIL) return 0; | ||||
|         if(flags & HARD_FAIL) exit(MEM_ENOMEM); | ||||
|          | ||||
|         if (file == NULL) | ||||
|             RAISE(OOM); // Out of memory exception | ||||
|         else // Called by macro | ||||
|             except_raise(&OOM, file, line); | ||||
|     } | ||||
|     return ptr; | ||||
| } | ||||
|  | ||||
| int mem_is_zero(const void *ptr, size_t nbytes) { | ||||
|     ASSERTED(ptr); | ||||
|     ASSERTED(nbytes > 0); | ||||
|     static const unsigned char zero_block[1024] = {0}; /* reused */ | ||||
|     while (nbytes >= sizeof(zero_block)) { | ||||
|         if (memcmp(ptr, zero_block, sizeof(zero_block)) != 0) | ||||
|             return 0; | ||||
|         ptr = (const unsigned char *)ptr + sizeof(zero_block); | ||||
|         nbytes -= sizeof(zero_block); | ||||
|     } | ||||
|     if (nbytes > 0 && memcmp(ptr, zero_block, nbytes) != 0) | ||||
|         return 0; | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										14
									
								
								tests/01_arena_new.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/01_arena_new.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| #define DEBUG | ||||
| #include <stdlib.h> | ||||
| #include <assert.h> | ||||
| #include "../include/arena.h" | ||||
| #include "../include/mem.h" | ||||
|  | ||||
| int main(void){ | ||||
|     size_t nbytes = 20; | ||||
|     Arena a = ARENA(0,nbytes); | ||||
|     assert(a.beg != NULL); | ||||
|     assert( mem_is_zero(a.beg, nbytes)); | ||||
|     free(a.beg); | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
							
								
								
									
										14
									
								
								tests/02_arena_nozero.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tests/02_arena_nozero.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| #define DEBUG | ||||
| #include <stdlib.h> | ||||
| #include <assert.h> | ||||
| #include "../include/arena.h" | ||||
| #include "../include/mem.h" | ||||
|  | ||||
| int main(void){ | ||||
|     size_t nbytes = 20; | ||||
|     Arena a = ARENA(NOZERO,nbytes); | ||||
|     assert(a.beg != NULL); | ||||
|     assert( !mem_is_zero(a.beg, nbytes)); | ||||
|     free(a.beg); | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
							
								
								
									
										12
									
								
								tests/03_arena_softfail.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tests/03_arena_softfail.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| #define DEBUG | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <assert.h> | ||||
| #include "../include/arena.h" | ||||
| #include "../include/mem.h" | ||||
| int main(void){ | ||||
|     size_t nbytes = MEM_GB(1024); | ||||
|     Arena a = ARENA(SOFT_FAIL, nbytes); | ||||
|     assert(a.beg == NULL); | ||||
|     return EXIT_SUCCESS; | ||||
| } | ||||
							
								
								
									
										30
									
								
								tests/04_arena_exception.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								tests/04_arena_exception.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| #define DEBUG | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <assert.h> | ||||
| #include "../include/arena.h" | ||||
|  | ||||
| #include "../include/mem.h" | ||||
| int main(void){ | ||||
|     size_t nbytes = MEM_GB(1024); | ||||
|     Arena a; | ||||
|     TRY { | ||||
|         a = ARENA(0,nbytes); /* try 1GB */ | ||||
|         if (!a.beg) | ||||
|             RAISE(OOM); | ||||
|         free(a.beg); | ||||
|     } | ||||
|     EXCEPT(OOM) { | ||||
|         /* handle memory failure gracefully */ | ||||
|         fprintf(stderr, "Caught: %s\n", OOM.reason); | ||||
|         return EXIT_SUCCESS; /* requested behavior */ | ||||
|     } | ||||
|     FINALLY { | ||||
|         /* cleanup if needed, runs always */ | ||||
|         if (a.beg) free(a.beg); | ||||
|     } | ||||
|     END_TRY; | ||||
|  | ||||
|     return EXIT_FAILURE; /* shouldn't reach here for this example */ | ||||
|   } | ||||
		Reference in New Issue
	
	Block a user