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. More...
 
void SDLTest_LogAllocations ()
 Print a log of any outstanding allocations. More...
 

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

◆ ADD_LINE

#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)
GLuint GLsizei const GLchar * message
static SDL_realloc_func SDL_realloc_orig
#define SDL_strlen

Referenced by SDLTest_LogAllocations().

Function Documentation

◆ get_allocation_bucket()

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().

57 {
58  CrcUint32 crc_value;
59  unsigned int index;
60  SDLTest_Crc32Calc(&s_crc32_context, (CrcUint8 *)&mem, sizeof(mem), &crc_value);
61  index = (crc_value & (SDL_arraysize(s_tracked_allocations) - 1));
62  return index;
63 }
static SDL_tracked_allocation * s_tracked_allocations[256]
GLuint index
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
#define CrcUint32
#define CrcUint8
int SDLTest_Crc32Calc(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32)
calculate a crc32 from a data block
static SDLTest_Crc32Context s_crc32_context

◆ SDL_IsAllocationTracked()

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().

66 {
68  int index = get_allocation_bucket(mem);
69  for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
70  if (mem == entry->mem) {
71  return SDL_TRUE;
72  }
73  }
74  return SDL_FALSE;
75 }
static unsigned int get_allocation_bucket(void *mem)
static SDL_tracked_allocation * s_tracked_allocations[256]
GLuint index
struct SDL_tracked_allocation * next

◆ SDL_TrackAllocation()

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().

78 {
80  int index = get_allocation_bucket(mem);
81 
82  if (SDL_IsAllocationTracked(mem)) {
83  return;
84  }
85  entry = (SDL_tracked_allocation *)SDL_malloc_orig(sizeof(*entry));
86  if (!entry) {
87  return;
88  }
89  entry->mem = mem;
90  entry->size = size;
91 
92  /* Generate the stack trace for the allocation */
93  SDL_zero(entry->stack);
94 #ifdef HAVE_LIBUNWIND_H
95  {
96  int stack_index;
97  unw_cursor_t cursor;
98  unw_context_t context;
99 
100  unw_getcontext(&context);
101  unw_init_local(&cursor, &context);
102 
103  stack_index = 0;
104  while (unw_step(&cursor) > 0) {
105  unw_word_t offset, pc;
106  char sym[256];
107 
108  unw_get_reg(&cursor, UNW_REG_IP, &pc);
109  entry->stack[stack_index] = pc;
110 
111  if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
112  snprintf(entry->stack_names[stack_index], sizeof(entry->stack_names[stack_index]), "%s+0x%llx", sym, offset);
113  }
114  ++stack_index;
115 
116  if (stack_index == SDL_arraysize(entry->stack)) {
117  break;
118  }
119  }
120  }
121 #endif /* HAVE_LIBUNWIND_H */
122 
123  entry->next = s_tracked_allocations[index];
124  s_tracked_allocations[index] = entry;
125 }
static unsigned int get_allocation_bucket(void *mem)
static screen_context_t context
Definition: video.c:25
GLintptr offset
static SDL_tracked_allocation * s_tracked_allocations[256]
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
static SDL_bool SDL_IsAllocationTracked(void *mem)
SDL_Cursor * cursor
Definition: testwm2.c:40
GLsizeiptr size
GLuint index
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
static SDL_malloc_func SDL_malloc_orig
struct SDL_tracked_allocation * next
char stack_names[10][256]

◆ SDL_UntrackAllocation()

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().

128 {
129  SDL_tracked_allocation *entry, *prev;
130  int index = get_allocation_bucket(mem);
131 
132  prev = NULL;
133  for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
134  if (mem == entry->mem) {
135  if (prev) {
136  prev->next = entry->next;
137  } else {
138  s_tracked_allocations[index] = entry->next;
139  }
140  SDL_free_orig(entry);
141  return;
142  }
143  prev = entry;
144  }
145 }
static unsigned int get_allocation_bucket(void *mem)
static SDL_tracked_allocation * s_tracked_allocations[256]
GLuint index
static SDL_free_func SDL_free_orig
#define NULL
Definition: begin_code.h:164
struct SDL_tracked_allocation * next

◆ SDLTest_LogAllocations()

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().

223 {
224  char *message = NULL;
225  size_t message_size = 0;
226  char line[128], *tmp;
227  SDL_tracked_allocation *entry;
228  int index, count, stack_index;
229  Uint64 total_allocated;
230 
231  if (!SDL_malloc_orig) {
232  return;
233  }
234 
235 #define ADD_LINE() \
236  message_size += (SDL_strlen(line) + 1); \
237  tmp = (char *)SDL_realloc_orig(message, message_size); \
238  if (!tmp) { \
239  return; \
240  } \
241  message = tmp; \
242  SDL_strlcat(message, line, message_size)
243 
244  SDL_strlcpy(line, "Memory allocations:\n", sizeof(line));
245  ADD_LINE();
246  SDL_strlcpy(line, "Expect 2 allocations from within SDL_GetErrBuf()\n", sizeof(line));
247  ADD_LINE();
248 
249  count = 0;
250  total_allocated = 0;
251  for (index = 0; index < SDL_arraysize(s_tracked_allocations); ++index) {
252  for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
253  SDL_snprintf(line, sizeof(line), "Allocation %d: %d bytes\n", count, (int)entry->size);
254  ADD_LINE();
255  /* Start at stack index 1 to skip our tracking functions */
256  for (stack_index = 1; stack_index < SDL_arraysize(entry->stack); ++stack_index) {
257  if (!entry->stack[stack_index]) {
258  break;
259  }
260  SDL_snprintf(line, sizeof(line), "\t0x%"SDL_PRIx64": %s\n", entry->stack[stack_index], entry->stack_names[stack_index]);
261  ADD_LINE();
262  }
263  total_allocated += entry->size;
264  ++count;
265  }
266  }
267  SDL_snprintf(line, sizeof(line), "Total: %.2f Kb in %d allocations\n", (float)total_allocated / 1024, count);
268  ADD_LINE();
269 #undef ADD_LINE
270 
271  SDL_Log("%s", message);
272 }
#define SDL_strlcpy
GLuint GLsizei const GLchar * message
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
uint64_t Uint64
Definition: SDL_stdinc.h:216
static SDL_tracked_allocation * s_tracked_allocations[256]
#define ADD_LINE()
#define SDL_Log
GLuint index
#define SDL_PRIx64
Definition: SDL_stdinc.h:249
#define NULL
Definition: begin_code.h:164
#define SDL_snprintf
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
static SDL_malloc_func SDL_malloc_orig
struct SDL_tracked_allocation * next
char stack_names[10][256]

◆ SDLTest_TrackAllocations()

int SDLTest_TrackAllocations ( )

Start tracking SDL memory allocations.

Note
This should be called before any other SDL functions for complete tracking coverage

Definition at line 197 of file SDL_test_memory.c.

References s_previous_allocations, SDL_calloc_orig, SDL_free_orig, SDL_GetMemoryFunctions, SDL_GetNumAllocations, SDL_Log, SDL_malloc_orig, SDL_realloc_orig, SDL_SetMemoryFunctions, SDLTest_Crc32Init(), SDLTest_TrackedCalloc(), SDLTest_TrackedFree(), SDLTest_TrackedMalloc(), and SDLTest_TrackedRealloc().

Referenced by SDLTest_CommonCreateState().

198 {
199  if (SDL_malloc_orig) {
200  return 0;
201  }
202 
204 
206  if (s_previous_allocations != 0) {
207  SDL_Log("SDLTest_TrackAllocations(): There are %d previous allocations, disabling free() validation", s_previous_allocations);
208  }
209 
213  &SDL_free_orig);
214 
219  return 0;
220 }
static int s_previous_allocations
static SDL_calloc_func SDL_calloc_orig
static void SDLTest_TrackedFree(void *ptr)
static void * SDLTest_TrackedMalloc(size_t size)
#define SDL_SetMemoryFunctions
static void * SDLTest_TrackedCalloc(size_t nmemb, size_t size)
static SDL_realloc_func SDL_realloc_orig
#define SDL_Log
#define SDL_GetMemoryFunctions
static SDL_free_func SDL_free_orig
int SDLTest_Crc32Init(SDLTest_Crc32Context *crcContext)
Initialize the CRC context.
static SDL_malloc_func SDL_malloc_orig
#define SDL_GetNumAllocations
static void * SDLTest_TrackedRealloc(void *ptr, size_t size)
static SDLTest_Crc32Context s_crc32_context

◆ SDLTest_TrackedCalloc()

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().

159 {
160  void *mem;
161 
162  mem = SDL_calloc_orig(nmemb, size);
163  if (mem) {
164  SDL_TrackAllocation(mem, nmemb * size);
165  }
166  return mem;
167 }
static SDL_calloc_func SDL_calloc_orig
static void SDL_TrackAllocation(void *mem, size_t size)
GLsizeiptr size

◆ SDLTest_TrackedFree()

static void SDLTest_TrackedFree ( void ptr)
static

Definition at line 184 of file SDL_test_memory.c.

References s_previous_allocations, SDL_assert, SDL_free_orig, SDL_IsAllocationTracked(), and SDL_UntrackAllocation().

Referenced by SDLTest_TrackAllocations().

185 {
186  if (!ptr) {
187  return;
188  }
189 
190  if (!s_previous_allocations) {
192  }
195 }
static int s_previous_allocations
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF ptr
static void SDL_UntrackAllocation(void *mem)
static SDL_bool SDL_IsAllocationTracked(void *mem)
static SDL_free_func SDL_free_orig
#define SDL_assert(condition)
Definition: SDL_assert.h:169

◆ SDLTest_TrackedMalloc()

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().

148 {
149  void *mem;
150 
151  mem = SDL_malloc_orig(size);
152  if (mem) {
154  }
155  return mem;
156 }
static void SDL_TrackAllocation(void *mem, size_t size)
GLsizeiptr size
static SDL_malloc_func SDL_malloc_orig

◆ SDLTest_TrackedRealloc()

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().

170 {
171  void *mem;
172 
174  mem = SDL_realloc_orig(ptr, size);
175  if (mem && mem != ptr) {
176  if (ptr) {
178  }
180  }
181  return mem;
182 }
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF ptr
static void SDL_TrackAllocation(void *mem, size_t size)
static SDL_realloc_func SDL_realloc_orig
static void SDL_UntrackAllocation(void *mem)
static SDL_bool SDL_IsAllocationTracked(void *mem)
GLsizeiptr size
#define SDL_assert(condition)
Definition: SDL_assert.h:169

Variable Documentation

◆ s_crc32_context

SDLTest_Crc32Context s_crc32_context
static

Definition at line 48 of file SDL_test_memory.c.

◆ s_previous_allocations

int s_previous_allocations = 0
static

Definition at line 53 of file SDL_test_memory.c.

Referenced by SDLTest_TrackAllocations(), and SDLTest_TrackedFree().

◆ s_tracked_allocations

SDL_tracked_allocation* s_tracked_allocations[256]
static

Definition at line 54 of file SDL_test_memory.c.

◆ SDL_calloc_orig

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_orig

SDL_free_func SDL_free_orig = NULL
static

◆ SDL_malloc_orig

◆ SDL_realloc_orig

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().