#ifndef INCLUDED_TEST_ALLOC_H #define INCLUDED_TEST_ALLOC_H #include #include #include #include #include #include #if defined(__has_attribute) && __has_attribute(unused) # define UNUSED __attribute__((unused)) #else # define UNUSED #endif static intmax_t _alloc_count = 0; static UNUSED void *counting_malloc(size_t size) { void *ptr = malloc(size); if (!ptr) { return NULL; } ++_alloc_count; return ptr; } static UNUSED void *counting_calloc(size_t n, size_t size) { void *ptr = calloc(n, size); if (!ptr) { return NULL; } ++_alloc_count; return ptr; } static UNUSED void *counting_realloc(void *old_ptr, size_t size) { if (!old_ptr) { return counting_malloc(size); } return realloc(old_ptr, size); } static UNUSED void counting_free(void *ptr) { if (ptr) { free(ptr); --_alloc_count; } } static UNUSED void check_allocator_status(void) { if (_alloc_count > 0) { fprintf(stderr, "Memory leak detected, allocation count is %jd!\n", _alloc_count); exit(EXIT_FAILURE); } else if (_alloc_count < 0) { fprintf(stderr, "%jd more free's that malloc's!", _alloc_count); exit(EXIT_FAILURE); } } static UNUSED char *counting_strdup(const char *str) { size_t len = strlen(str); char *ns = counting_malloc(len + 1); strcpy(ns, str); return ns; } static UNUSED const RefcountAllocator COUNTING_ALLOCATOR = { .malloc.no_data = counting_malloc, .free.no_data = counting_free, }; #endif