// // Safe malloc with error file:line logging, using the FreeRTOS-provided malloc facility // The custom malloc implementation is safer than the poorly documented hacks provided by // newlib, written primarily for the desktop rather than embedded. // #ifndef MALLOC_SAFE_H #define MALLOC_SAFE_H /** * Malloc that prints error and restarts the system on failure. */ #include #include #include void *malloc_ck_do(size_t size, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); void *calloc_ck_do(size_t nmemb, size_t size, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); char *strdup_ck_do(const char *s, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); char *strndup_ck_do(const char *s, uint32_t len, const char* file, uint32_t line) __attribute__((malloc,warn_unused_result)); #if DEBUG_MALLOC #define _malloc_trace(len, obj, file, line) do { PRINTF("~ malloc(%d) -> 0x%p at ", len, obj); PUTS(file); PUTCHAR(':'); PRINTF("%d\r\n", (int)line); } while (0) #define _free_trace(obj, file, line) do { PRINTF("~ free(0x%p) at ", obj); PUTS(file); PUTCHAR(':'); PRINTF("%d\r\n", (int)line); } while (0) #define malloc_ck(size) malloc_ck_do(size, __BASE_FILE__, __LINE__) #define calloc_ck(nmemb, size) calloc_ck_do(nmemb, size, __BASE_FILE__, __LINE__) #define strdup_ck(s) strdup_ck_do(s, __BASE_FILE__, __LINE__) #define strndup_ck(s, len) strndup_ck_do(s, (uint32_t)(len), __BASE_FILE__, __LINE__) #else #define _malloc_trace(len, obj, file, line) #define _free_trace(obj, file, line) #define malloc_ck(size) malloc_ck_do(size, "", 0) #define calloc_ck(nmemb, size) calloc_ck_do(nmemb, size, "", 0) #define strdup_ck(s) strdup_ck_do(s, "", 0) #define strndup_ck(s, len) strndup_ck_do(s, (uint32_t)(len), "", 0) #endif /** * Free an allocated object, and assign it to NULL. */ #define free_ck(obj) do { \ _free_trace(obj, __BASE_FILE__, __LINE__); \ if ((obj) != NULL) vPortFree((void *)(obj)); \ obj = NULL; \ } while (0) #endif // MALLOC_SAFE_H