mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2026-01-27 18:24:27 +01:00
Add configuration option UNITY_EXCLUDE_STDLIB_MALLOC to Fixture
This feature removes the dependency on malloc/free for constrained embedded systems without a heap. It uses a static heap inside Unity Fixture. Setting UNITY_INTERNAL_HEAP_SIZE_BYTES sizes the heap. Add tests for new option, add targets to makefile for running tests. UNITY_FIXTURE_MALLOC for Fixture use only, remove from unity_output_Spy.c.
This commit is contained in:
@@ -156,7 +156,12 @@ void UnityMalloc_MakeMallocFailAfterCount(int countdown)
|
||||
#undef calloc
|
||||
#undef realloc
|
||||
|
||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||
static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
|
||||
static unsigned int heap_index;
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
typedef struct GuardBytes
|
||||
{
|
||||
@@ -171,19 +176,31 @@ void* unity_malloc(size_t size)
|
||||
{
|
||||
char* mem;
|
||||
Guard* guard;
|
||||
size_t total_size = size + sizeof(Guard) + sizeof(end);
|
||||
|
||||
if (malloc_fail_countdown != MALLOC_DONT_FAIL)
|
||||
{
|
||||
if (malloc_fail_countdown == 0)
|
||||
return 0;
|
||||
return NULL;
|
||||
malloc_fail_countdown--;
|
||||
}
|
||||
|
||||
if (size == 0) return NULL;
|
||||
malloc_count++;
|
||||
|
||||
guard = (Guard*)UNITY_FIXTURE_MALLOC(size + sizeof(Guard) + sizeof(end));
|
||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||
if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES)
|
||||
{
|
||||
guard = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
guard = (Guard*) &unity_heap[heap_index];
|
||||
heap_index += total_size;
|
||||
}
|
||||
#else
|
||||
guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size);
|
||||
#endif
|
||||
if (guard == NULL) return NULL;
|
||||
malloc_count++;
|
||||
guard->size = size;
|
||||
mem = (char*)&(guard[1]);
|
||||
memcpy(&mem[size], end, sizeof(end));
|
||||
@@ -206,7 +223,14 @@ static void release_memory(void* mem)
|
||||
guard--;
|
||||
|
||||
malloc_count--;
|
||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||
if (mem == unity_heap + heap_index - guard->size - sizeof(end))
|
||||
{
|
||||
heap_index -= (guard->size + sizeof(Guard) + sizeof(end));
|
||||
}
|
||||
#else
|
||||
UNITY_FIXTURE_FREE(guard);
|
||||
#endif
|
||||
}
|
||||
|
||||
void unity_free(void* mem)
|
||||
@@ -218,7 +242,7 @@ void unity_free(void* mem)
|
||||
return;
|
||||
}
|
||||
|
||||
overrun = isOverrun(mem);//strcmp(&memAsChar[guard->size], end) != 0;
|
||||
overrun = isOverrun(mem);
|
||||
release_memory(mem);
|
||||
if (overrun)
|
||||
{
|
||||
@@ -230,14 +254,13 @@ void* unity_calloc(size_t num, size_t size)
|
||||
{
|
||||
void* mem = unity_malloc(num * size);
|
||||
if (mem == NULL) return NULL;
|
||||
memset(mem, 0, num*size);
|
||||
memset(mem, 0, num * size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void* unity_realloc(void* oldMem, size_t size)
|
||||
{
|
||||
Guard* guard = (Guard*)oldMem;
|
||||
// char* memAsChar = (char*)oldMem;
|
||||
void* newMem;
|
||||
|
||||
if (oldMem == NULL) return unity_malloc(size);
|
||||
@@ -257,10 +280,18 @@ void* unity_realloc(void* oldMem, size_t size)
|
||||
|
||||
if (guard->size >= size) return oldMem;
|
||||
|
||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC // Optimization if memory is expandable
|
||||
if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) &&
|
||||
heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES)
|
||||
{
|
||||
release_memory(oldMem); // Not thread-safe, like unity_heap generally
|
||||
return unity_malloc(size); // No memcpy since data is in place
|
||||
}
|
||||
#endif
|
||||
newMem = unity_malloc(size);
|
||||
if (newMem == NULL) return NULL; // Do not release old memory
|
||||
memcpy(newMem, oldMem, guard->size);
|
||||
unity_free(oldMem);
|
||||
release_memory(oldMem);
|
||||
return newMem;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,11 +10,21 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
|
||||
// Define this macro to remove the use of stdlib.h, malloc, and free.
|
||||
// Many embedded systems do not have a heap or malloc/free by default.
|
||||
// This internal unity_malloc() provides allocated memory deterministically from
|
||||
// the end of an array only, unity_free() only releases from end-of-array,
|
||||
// blocks are not coalesced, and memory not freed in LIFO order is stranded.
|
||||
#ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES
|
||||
#define UNITY_INTERNAL_HEAP_SIZE_BYTES 256
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// These functions are used by the Unity Fixture to allocate and release memory
|
||||
// on the heap and can be overridden with platform-specific implementations.
|
||||
// For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc()
|
||||
// and UNITY_FIXTURE_FREE becomes vPortFree().
|
||||
|
||||
#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE)
|
||||
#define UNITY_FIXTURE_MALLOC(size) malloc(size)
|
||||
#define UNITY_FIXTURE_FREE(ptr) free(ptr)
|
||||
|
||||
Reference in New Issue
Block a user