Fixed bug 3879 - add missing SDLCALL to SDLTest_TrackedMalloc & co.
Ozkan Sezer
The attached trivial patch adds missing SDLCALL to SDLTest_TrackedMalloc & co.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
21 #include "SDL_config.h"
22 #include "SDL_assert.h"
23 #include "SDL_stdinc.h"
25 #include "SDL_test_crc32.h"
26 #include "SDL_test_memory.h"
28 #ifdef HAVE_LIBUNWIND_H
29 #include <libunwind.h>
32 /* This is a simple tracking allocator to demonstrate the use of SDL's
33 memory allocation replacement functionality.
35 It gets slow with large numbers of allocations and shouldn't be used
39 typedef struct SDL_tracked_allocation
44 char stack_names[10][256];
45 struct SDL_tracked_allocation *next;
46 } SDL_tracked_allocation;
48 static SDLTest_Crc32Context s_crc32_context;
49 static SDL_malloc_func SDL_malloc_orig = NULL;
50 static SDL_calloc_func SDL_calloc_orig = NULL;
51 static SDL_realloc_func SDL_realloc_orig = NULL;
52 static SDL_free_func SDL_free_orig = NULL;
53 static int s_previous_allocations = 0;
54 static SDL_tracked_allocation *s_tracked_allocations[256];
56 static unsigned int get_allocation_bucket(void *mem)
60 SDLTest_Crc32Calc(&s_crc32_context, (CrcUint8 *)&mem, sizeof(mem), &crc_value);
61 index = (crc_value & (SDL_arraysize(s_tracked_allocations) - 1));
65 static SDL_bool SDL_IsAllocationTracked(void *mem)
67 SDL_tracked_allocation *entry;
68 int index = get_allocation_bucket(mem);
69 for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
70 if (mem == entry->mem) {
77 static void SDL_TrackAllocation(void *mem, size_t size)
79 SDL_tracked_allocation *entry;
80 int index = get_allocation_bucket(mem);
82 if (SDL_IsAllocationTracked(mem)) {
85 entry = (SDL_tracked_allocation *)SDL_malloc_orig(sizeof(*entry));
92 /* Generate the stack trace for the allocation */
93 SDL_zero(entry->stack);
94 #ifdef HAVE_LIBUNWIND_H
98 unw_context_t context;
100 unw_getcontext(&context);
101 unw_init_local(&cursor, &context);
104 while (unw_step(&cursor) > 0) {
105 unw_word_t offset, pc;
108 unw_get_reg(&cursor, UNW_REG_IP, &pc);
109 entry->stack[stack_index] = pc;
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);
116 if (stack_index == SDL_arraysize(entry->stack)) {
121 #endif /* HAVE_LIBUNWIND_H */
123 entry->next = s_tracked_allocations[index];
124 s_tracked_allocations[index] = entry;
127 static void SDL_UntrackAllocation(void *mem)
129 SDL_tracked_allocation *entry, *prev;
130 int index = get_allocation_bucket(mem);
133 for (entry = s_tracked_allocations[index]; entry; entry = entry->next) {
134 if (mem == entry->mem) {
136 prev->next = entry->next;
138 s_tracked_allocations[index] = entry->next;
140 SDL_free_orig(entry);
147 static void * SDLCALL SDLTest_TrackedMalloc(size_t size)
151 mem = SDL_malloc_orig(size);
153 SDL_TrackAllocation(mem, size);
158 static void * SDLCALL SDLTest_TrackedCalloc(size_t nmemb, size_t size)
162 mem = SDL_calloc_orig(nmemb, size);
164 SDL_TrackAllocation(mem, nmemb * size);
169 static void * SDLCALL SDLTest_TrackedRealloc(void *ptr, size_t size)
173 SDL_assert(!ptr || SDL_IsAllocationTracked(ptr));
174 mem = SDL_realloc_orig(ptr, size);
175 if (mem && mem != ptr) {
177 SDL_UntrackAllocation(ptr);
179 SDL_TrackAllocation(mem, size);
184 static void SDLCALL SDLTest_TrackedFree(void *ptr)
190 if (!s_previous_allocations) {
191 SDL_assert(SDL_IsAllocationTracked(ptr));
193 SDL_UntrackAllocation(ptr);
197 int SDLTest_TrackAllocations()
199 if (SDL_malloc_orig) {
203 SDLTest_Crc32Init(&s_crc32_context);
205 s_previous_allocations = SDL_GetNumAllocations();
206 if (s_previous_allocations != 0) {
207 SDL_Log("SDLTest_TrackAllocations(): There are %d previous allocations, disabling free() validation", s_previous_allocations);
210 SDL_GetMemoryFunctions(&SDL_malloc_orig,
215 SDL_SetMemoryFunctions(SDLTest_TrackedMalloc,
216 SDLTest_TrackedCalloc,
217 SDLTest_TrackedRealloc,
218 SDLTest_TrackedFree);
222 void SDLTest_LogAllocations()
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;
231 if (!SDL_malloc_orig) {
236 message_size += (SDL_strlen(line) + 1); \
237 tmp = (char *)SDL_realloc_orig(message, message_size); \
242 SDL_strlcat(message, line, message_size)
244 SDL_strlcpy(line, "Memory allocations:\n", sizeof(line));
246 SDL_strlcpy(line, "Expect 2 allocations from within SDL_GetErrBuf()\n", sizeof(line));
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);
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]) {
260 SDL_snprintf(line, sizeof(line), "\t0x%"SDL_PRIx64": %s\n", entry->stack[stack_index], entry->stack_names[stack_index]);
263 total_allocated += entry->size;
267 SDL_snprintf(line, sizeof(line), "Total: %.2f Kb in %d allocations\n", (float)total_allocated / 1024, count);
271 SDL_Log("%s", message);
274 /* vi: set ts=4 sw=4 expandtab: */