SDL  2.0
SDL_test_memory.c File Reference
#include "SDL_config.h"
#include "SDL_assert.h"
#include "SDL_stdinc.h"
#include "SDL_log.h"
#include "SDL_test_crc32.h"
#include "SDL_test_memory.h"
+ Include dependency graph for SDL_test_memory.c:

Go to the source code of this file.

Data Structures

struct  SDL_tracked_allocation

Macros

#define ADD_LINE()

Functions

static unsigned int get_allocation_bucket (void *mem)
static SDL_bool SDL_IsAllocationTracked (void *mem)
static void SDL_TrackAllocation (void *mem, size_t size)
static void SDL_UntrackAllocation (void *mem)
static voidSDLTest_TrackedMalloc (size_t size)
static voidSDLTest_TrackedCalloc (size_t nmemb, size_t size)
static voidSDLTest_TrackedRealloc (void *ptr, size_t size)
static void SDLTest_TrackedFree (void *ptr)
int SDLTest_TrackAllocations ()
 Start tracking SDL memory allocations.
void SDLTest_LogAllocations ()
 Print a log of any outstanding allocations.

Variables

static SDLTest_Crc32Context s_crc32_context
static SDL_malloc_func SDL_malloc_orig = NULL
static SDL_calloc_func SDL_calloc_orig = NULL
static SDL_realloc_func SDL_realloc_orig = NULL
static SDL_free_func SDL_free_orig = NULL
static int s_previous_allocations = 0
static SDL_tracked_allocations_tracked_allocations [256]

Macro Definition Documentation

#define ADD_LINE ( )
Value:
message_size += (SDL_strlen(line) + 1); \
tmp = (char *)SDL_realloc_orig(message, message_size); \
if (!tmp) { \
return; \
} \
message = tmp; \
SDL_strlcat(message, line, message_size)

Referenced by SDLTest_LogAllocations().

Function Documentation

static unsigned int get_allocation_bucket ( void mem)
static

Definition at line 56 of file SDL_test_memory.c.

References CrcUint32, CrcUint8, SDL_arraysize, and SDLTest_Crc32Calc().

Referenced by SDL_IsAllocationTracked(), SDL_TrackAllocation(), and SDL_UntrackAllocation().

{
CrcUint32 crc_value;
unsigned int index;
SDLTest_Crc32Calc(&s_crc32_context, (CrcUint8 *)&mem, sizeof(mem), &crc_value);
index = (crc_value & (SDL_arraysize(s_tracked_allocations) - 1));
return index;
}
static SDL_bool SDL_IsAllocationTracked ( void mem)
static

Definition at line 65 of file SDL_test_memory.c.

References get_allocation_bucket(), SDL_tracked_allocation::mem, SDL_tracked_allocation::next, SDL_FALSE, and SDL_TRUE.

Referenced by SDL_TrackAllocation(), SDLTest_TrackedFree(), and SDLTest_TrackedRealloc().

{
for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
if (mem == entry->mem) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}
static void SDL_TrackAllocation ( void mem,
size_t  size 
)
static

Definition at line 77 of file SDL_test_memory.c.

References context, cursor, get_allocation_bucket(), SDL_tracked_allocation::mem, SDL_tracked_allocation::next, SDL_arraysize, SDL_IsAllocationTracked(), SDL_malloc_orig, SDL_zero, SDL_tracked_allocation::size, SDL_tracked_allocation::stack, and SDL_tracked_allocation::stack_names.

Referenced by SDLTest_TrackedCalloc(), SDLTest_TrackedMalloc(), and SDLTest_TrackedRealloc().

{
return;
}
entry = (SDL_tracked_allocation *)SDL_malloc_orig(sizeof(*entry));
if (!entry) {
return;
}
entry->mem = mem;
entry->size = size;
/* Generate the stack trace for the allocation */
SDL_zero(entry->stack);
#ifdef HAVE_LIBUNWIND_H
{
int stack_index;
unw_cursor_t cursor;
unw_context_t context;
unw_getcontext(&context);
unw_init_local(&cursor, &context);
stack_index = 0;
while (unw_step(&cursor) > 0) {
unw_word_t offset, pc;
char sym[256];
unw_get_reg(&cursor, UNW_REG_IP, &pc);
entry->stack[stack_index] = pc;
if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
snprintf(entry->stack_names[stack_index], sizeof(entry->stack_names[stack_index]), "%s+0x%llx", sym, offset);
}
++stack_index;
if (stack_index == SDL_arraysize(entry->stack)) {
break;
}
}
}
#endif /* HAVE_LIBUNWIND_H */
}
static void SDL_UntrackAllocation ( void mem)
static

Definition at line 127 of file SDL_test_memory.c.

References get_allocation_bucket(), SDL_tracked_allocation::mem, SDL_tracked_allocation::next, NULL, and SDL_free_orig.

Referenced by SDLTest_TrackedFree(), and SDLTest_TrackedRealloc().

{
SDL_tracked_allocation *entry, *prev;
prev = NULL;
for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
if (mem == entry->mem) {
if (prev) {
prev->next = entry->next;
} else {
}
SDL_free_orig(entry);
return;
}
prev = entry;
}
}
void SDLTest_LogAllocations ( )

Print a log of any outstanding allocations.

Note
This can be called after SDL_Quit()

Definition at line 222 of file SDL_test_memory.c.

References ADD_LINE, SDL_tracked_allocation::next, NULL, SDL_arraysize, SDL_Log, SDL_malloc_orig, SDL_PRIx64, SDL_snprintf, SDL_strlcpy, SDL_tracked_allocation::size, SDL_tracked_allocation::stack, and SDL_tracked_allocation::stack_names.

Referenced by SDLTest_CommonQuit().

{
char *message = NULL;
size_t message_size = 0;
char line[128], *tmp;
int index, count, stack_index;
Uint64 total_allocated;
return;
}
#define ADD_LINE() \
message_size += (SDL_strlen(line) + 1); \
tmp = (char *)SDL_realloc_orig(message, message_size); \
if (!tmp) { \
return; \
} \
message = tmp; \
SDL_strlcat(message, line, message_size)
SDL_strlcpy(line, "Memory allocations:\n", sizeof(line));
SDL_strlcpy(line, "Expect 2 allocations from within SDL_GetErrBuf()\n", sizeof(line));
count = 0;
total_allocated = 0;
for (index = 0; index < SDL_arraysize(s_tracked_allocations); ++index) {
for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
SDL_snprintf(line, sizeof(line), "Allocation %d: %d bytes\n", count, (int)entry->size);
/* Start at stack index 1 to skip our tracking functions */
for (stack_index = 1; stack_index < SDL_arraysize(entry->stack); ++stack_index) {
if (!entry->stack[stack_index]) {
break;
}
SDL_snprintf(line, sizeof(line), "\t0x%"SDL_PRIx64": %s\n", entry->stack[stack_index], entry->stack_names[stack_index]);
}
total_allocated += entry->size;
++count;
}
}
SDL_snprintf(line, sizeof(line), "Total: %.2f Kb in %d allocations\n", (float)total_allocated / 1024, count);
#undef ADD_LINE
SDL_Log("%s", message);
}
int SDLTest_TrackAllocations ( )
static void* SDLTest_TrackedCalloc ( size_t  nmemb,
size_t  size 
)
static

Definition at line 158 of file SDL_test_memory.c.

References SDL_tracked_allocation::mem, SDL_calloc_orig, and SDL_TrackAllocation().

Referenced by SDLTest_TrackAllocations().

{
void *mem;
mem = SDL_calloc_orig(nmemb, size);
if (mem) {
SDL_TrackAllocation(mem, nmemb * size);
}
return mem;
}
static void SDLTest_TrackedFree ( void ptr)
static
static void* SDLTest_TrackedMalloc ( size_t  size)
static

Definition at line 147 of file SDL_test_memory.c.

References SDL_tracked_allocation::mem, SDL_malloc_orig, and SDL_TrackAllocation().

Referenced by SDLTest_TrackAllocations().

{
void *mem;
if (mem) {
}
return mem;
}
static void* SDLTest_TrackedRealloc ( void ptr,
size_t  size 
)
static

Definition at line 169 of file SDL_test_memory.c.

References SDL_tracked_allocation::mem, SDL_assert, SDL_IsAllocationTracked(), SDL_realloc_orig, SDL_TrackAllocation(), and SDL_UntrackAllocation().

Referenced by SDLTest_TrackAllocations().

{
void *mem;
mem = SDL_realloc_orig(ptr, size);
if (mem && mem != ptr) {
if (ptr) {
}
}
return mem;
}

Variable Documentation

SDLTest_Crc32Context s_crc32_context
static

Definition at line 48 of file SDL_test_memory.c.

int s_previous_allocations = 0
static

Definition at line 53 of file SDL_test_memory.c.

Referenced by SDLTest_TrackAllocations(), and SDLTest_TrackedFree().

SDL_tracked_allocation* s_tracked_allocations[256]
static

Definition at line 54 of file SDL_test_memory.c.

SDL_calloc_func SDL_calloc_orig = NULL
static

Definition at line 50 of file SDL_test_memory.c.

Referenced by SDLTest_TrackAllocations(), and SDLTest_TrackedCalloc().

SDL_free_func SDL_free_orig = NULL
static
SDL_realloc_func SDL_realloc_orig = NULL
static

Definition at line 51 of file SDL_test_memory.c.

Referenced by SDLTest_TrackAllocations(), and SDLTest_TrackedRealloc().