#ifndef GMEM_H_ #define GMEM_H_ /* * A set of macros / functions to allocate and release dynamic memory. * * When compiling with GMEM_CHECK defined, the macros keep track of all memory * allocation and deallocation, and a summary is printed out at the end; when * it is undefined, the macros are equivalent to raw calls to malloc / realloc * / free, thus incurring no runtime cost; additionally, in this case when * freeing, the freed variable is set to zero. * * Examples for calling the macros: * * GMEM_NEW(header, Header*, sizeof(Header)) * => header = (Header*) malloc(sizeof(Header)) * * GMEM_REALLOC(data, Data*, 20, 30) * => data = (Data*) realloc(data, 40), set last 10 elements to 0 * * GMEM_DEL(header, Header*, sizeof(Header)) * => free(header), header = 0 * * GMEM_NEWARR(data, Data*, 10, sizeof(Data)) * => data = (Data*) calloc(40, sizeof(Dasta)) * * GMEM_DELARR(data, Data*, 10, sizeof(Data)) * => free(data), data = 0 */ #include #include #define _GMEM_NEW(scalar, type, size) \ do { \ scalar = (type) malloc(size); \ } while (0) #define _GMEM_REALLOC(scalar, type, osize, nsize) \ do { \ scalar = (type) realloc(scalar, nsize); \ } while (0) #define _GMEM_DEL(scalar, type, size) \ do { \ free(scalar); \ scalar = 0; \ } while (0) #if !defined(GMEM_CHECK) || GMEM_CHECK < 1 #define GMEM_NEW(scalar, type, size) _GMEM_NEW(scalar, type, size) #define GMEM_REALLOC(scalar, type, osize, nsize) _GMEM_REALLOC(scalar, type, osize, nsize) #define GMEM_DEL(scalar, type, size) _GMEM_DEL(scalar, type, size) #define GMEM_NEWARR(array, type, count, size) \ do { \ array = (type) calloc(count, size); \ } while (0) #define GMEM_DELARR(array, type, count, size) \ do { \ free(array); \ array = 0; \ } while (0) #define GMEM_NEWSTR(tgt, src, len, ret) \ do { \ tgt = 0; \ if (!src) { \ ret = 0; \ break; \ } \ int l = len <= 0 ? strlen(src) + 1 : len; \ _GMEM_NEW(tgt, char*, l); \ memcpy(tgt, src, l); \ ret = l; \ } while (0) #define GMEM_DELSTR(str, len) \ do { \ _GMEM_DEL(str, char*, len); \ } while (0) #else #define GMEM_NEW(scalar, type, size) \ do { \ _GMEM_NEW(scalar, type, size); \ gmem_new_called(__FILE__, __LINE__, scalar, 1, size); \ } while (0) #define GMEM_REALLOC(scalar, type, osize, nsize) \ do { \ gmem_del_called(__FILE__, __LINE__, scalar, 1, osize); \ _GMEM_REALLOC(scalar, type, osize, nsize); \ gmem_new_called(__FILE__, __LINE__, scalar, 1, nsize); \ } while (0) #define GMEM_DEL(scalar, type, size) \ do { \ gmem_del_called(__FILE__, __LINE__, scalar, 1, size); \ _GMEM_DEL(scalar, type, size); \ } while (0) #define GMEM_NEWARR(array, type, count, size) \ do { \ array = (type) calloc(count, size); \ gmem_new_called(__FILE__, __LINE__, array, count, size); \ } while (0) #define GMEM_DELARR(array, type, count, size) \ do { \ gmem_del_called(__FILE__, __LINE__, array, count, size); \ free(array); \ array = 0; \ } while (0) #define GMEM_NEWSTR(tgt, src, len, ret) \ do { \ ret = gmem_strnew(__FILE__, __LINE__, &tgt, src, len); \ } while (0) #define GMEM_DELSTR(str, len) \ do { \ gmem_strdel(__FILE__, __LINE__, &str, len); \ } while (0) extern long gmem_new; extern long gmem_del; int gmem_new_called(const char* file, int line, void* var, int count, long size); int gmem_del_called(const char* file, int line, void* var, int count, long size); int gmem_strnew(const char* file, int line, char** tgt, const char* src, int len); int gmem_strdel(const char* file, int line, char** str, int len); #endif /* #if !defined(GMEM_CHECK) || GMEM_CHECK < 1 */ #endif