Browse Source

Added functions to query and set the SDL memory allocation functions:
SDL_GetMemoryFunctions()
SDL_SetMemoryFunctions()
SDL_GetNumAllocations()

Sam Lantinga 7 years ago
parent
commit
9c580e14c9

+ 2 - 2
CMakeLists.txt

@@ -653,7 +653,7 @@ if(LIBC)
     check_include_file(sys/types.h HAVE_SYS_TYPES_H)
     foreach(_HEADER
             stdio.h stdlib.h stddef.h stdarg.h malloc.h memory.h string.h limits.h
-            strings.h wchar.h inttypes.h stdint.h ctype.h math.h iconv.h signal.h)
+            strings.h wchar.h inttypes.h stdint.h ctype.h math.h iconv.h signal.h libunwind.h)
       string(TOUPPER "HAVE_${_HEADER}" _UPPER)
       string(REPLACE "." "_" _HAVE_H ${_UPPER})
       check_include_file("${_HEADER}" ${_HAVE_H})
@@ -669,7 +669,7 @@ if(LIBC)
     foreach(_FN
             strtod malloc calloc realloc free getenv setenv putenv unsetenv
             qsort abs bcopy memset memcpy memmove memcmp strlen strlcpy strlcat
-            strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa
+            _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa
             _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull
             atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp
             vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction setjmp

+ 2 - 1
VisualC/SDLtest/SDLtest.vcxproj

@@ -164,9 +164,10 @@
     <ClCompile Include="..\..\src\test\SDL_test_imagePrimitivesBlend.c" />
     <ClCompile Include="..\..\src\test\SDL_test_log.c" />
     <ClCompile Include="..\..\src\test\SDL_test_md5.c" />
+    <ClCompile Include="..\..\src\test\SDL_test_memory.c" />
     <ClCompile Include="..\..\src\test\SDL_test_random.c" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>

+ 4 - 0
WhatsNew.txt

@@ -6,6 +6,10 @@ This is a list of major changes in SDL's version history.
 ---------------------------------------------------------------------------
 
 General:
+* Added functions to query and set the SDL memory allocation functions:
+	SDL_GetMemoryFunctions()
+	SDL_SetMemoryFunctions()
+	SDL_GetNumAllocations()
 * Added locking functions for multi-threaded access to the joystick and game controller APIs:
 	SDL_LockJoysticks()
 	SDL_UnlockJoysticks()

+ 8 - 0
Xcode-iOS/SDLtest/SDL2test.xcodeproj/project.pbxproj

@@ -21,6 +21,8 @@
 		AA1EE46D176059AB0029C7A5 /* SDL_test_log.c in Sources */ = {isa = PBXBuildFile; fileRef = AA1EE45F176059AB0029C7A5 /* SDL_test_log.c */; };
 		AA1EE46E176059AB0029C7A5 /* SDL_test_md5.c in Sources */ = {isa = PBXBuildFile; fileRef = AA1EE460176059AB0029C7A5 /* SDL_test_md5.c */; };
 		AA1EE46F176059AB0029C7A5 /* SDL_test_random.c in Sources */ = {isa = PBXBuildFile; fileRef = AA1EE461176059AB0029C7A5 /* SDL_test_random.c */; };
+		AAF030011F9009B100B9A9FB /* SDL_test_memory.c in Sources */ = {isa = PBXBuildFile; fileRef = AAF02FFF1F9009B100B9A9FB /* SDL_test_memory.c */; };
+		AAF030021F9009B100B9A9FB /* SDL_test_assert.c in Sources */ = {isa = PBXBuildFile; fileRef = AAF030001F9009B100B9A9FB /* SDL_test_assert.c */; };
 		FA3D99011BC4E5BC002C96C8 /* SDL_test_common.c in Sources */ = {isa = PBXBuildFile; fileRef = AA1EE454176059AB0029C7A5 /* SDL_test_common.c */; };
 		FA3D99021BC4E5BC002C96C8 /* SDL_test_compare.c in Sources */ = {isa = PBXBuildFile; fileRef = AA1EE455176059AB0029C7A5 /* SDL_test_compare.c */; };
 		FA3D99031BC4E5BC002C96C8 /* SDL_test_crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = AA1EE456176059AB0029C7A5 /* SDL_test_crc32.c */; };
@@ -65,6 +67,8 @@
 		AA1EE45F176059AB0029C7A5 /* SDL_test_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_test_log.c; path = ../../src/test/SDL_test_log.c; sourceTree = "<group>"; };
 		AA1EE460176059AB0029C7A5 /* SDL_test_md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_test_md5.c; path = ../../src/test/SDL_test_md5.c; sourceTree = "<group>"; };
 		AA1EE461176059AB0029C7A5 /* SDL_test_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_test_random.c; path = ../../src/test/SDL_test_random.c; sourceTree = "<group>"; };
+		AAF02FFF1F9009B100B9A9FB /* SDL_test_memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_test_memory.c; path = ../../src/test/SDL_test_memory.c; sourceTree = "<group>"; };
+		AAF030001F9009B100B9A9FB /* SDL_test_assert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_test_assert.c; path = ../../src/test/SDL_test_assert.c; sourceTree = "<group>"; };
 		FA3D98F81BC4E5A2002C96C8 /* libSDL2test-TV.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libSDL2test-TV.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
@@ -106,6 +110,7 @@
 		AA1EE453176059770029C7A5 /* Library Source */ = {
 			isa = PBXGroup;
 			children = (
+				AAF030001F9009B100B9A9FB /* SDL_test_assert.c */,
 				AA1EE454176059AB0029C7A5 /* SDL_test_common.c */,
 				AA1EE455176059AB0029C7A5 /* SDL_test_compare.c */,
 				AA1EE456176059AB0029C7A5 /* SDL_test_crc32.c */,
@@ -119,6 +124,7 @@
 				AA1EE45E176059AB0029C7A5 /* SDL_test_imagePrimitivesBlend.c */,
 				AA1EE45F176059AB0029C7A5 /* SDL_test_log.c */,
 				AA1EE460176059AB0029C7A5 /* SDL_test_md5.c */,
+				AAF02FFF1F9009B100B9A9FB /* SDL_test_memory.c */,
 				AA1EE461176059AB0029C7A5 /* SDL_test_random.c */,
 			);
 			name = "Library Source";
@@ -213,12 +219,14 @@
 				AA1EE464176059AB0029C7A5 /* SDL_test_crc32.c in Sources */,
 				AA1EE465176059AB0029C7A5 /* SDL_test_font.c in Sources */,
 				AA1EE466176059AB0029C7A5 /* SDL_test_fuzzer.c in Sources */,
+				AAF030021F9009B100B9A9FB /* SDL_test_assert.c in Sources */,
 				AA1EE467176059AB0029C7A5 /* SDL_test_harness.c in Sources */,
 				AA1EE468176059AB0029C7A5 /* SDL_test_imageBlit.c in Sources */,
 				AA1EE469176059AB0029C7A5 /* SDL_test_imageBlitBlend.c in Sources */,
 				AA1EE46A176059AB0029C7A5 /* SDL_test_imageFace.c in Sources */,
 				AA1EE46B176059AB0029C7A5 /* SDL_test_imagePrimitives.c in Sources */,
 				AA1EE46C176059AB0029C7A5 /* SDL_test_imagePrimitivesBlend.c in Sources */,
+				AAF030011F9009B100B9A9FB /* SDL_test_memory.c in Sources */,
 				AA1EE46D176059AB0029C7A5 /* SDL_test_log.c in Sources */,
 				AA1EE46E176059AB0029C7A5 /* SDL_test_md5.c in Sources */,
 				AA1EE46F176059AB0029C7A5 /* SDL_test_random.c in Sources */,

+ 4 - 0
Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj

@@ -348,6 +348,7 @@
 		00794EF009D23739003FC8A1 /* utf8.txt in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00794E6309D20839003FC8A1 /* utf8.txt */; };
 		00794EF709D237DE003FC8A1 /* moose.dat in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00794E5E09D20839003FC8A1 /* moose.dat */; };
 		453774A5120915E3002F0F45 /* testshape.c in Sources */ = {isa = PBXBuildFile; fileRef = 453774A4120915E3002F0F45 /* testshape.c */; };
+		AAF02FFA1F90092700B9A9FB /* SDL_test_memory.c in Sources */ = {isa = PBXBuildFile; fileRef = AAF02FF41F90089800B9A9FB /* SDL_test_memory.c */; };
 		BBFC08C0164C6862003E6A99 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002F33A709CA188600EBEB88 /* Cocoa.framework */; };
 		BBFC08C1164C6862003E6A99 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A863B10730545007319AE /* CoreAudio.framework */; };
 		BBFC08C2164C6862003E6A99 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 002A863C10730545007319AE /* ForceFeedback.framework */; };
@@ -1152,6 +1153,7 @@
 		092D6D75FFB313BB7F000001 /* testlock.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = testlock.c; path = ../../test/testlock.c; sourceTree = SOURCE_ROOT; };
 		4537749212091504002F0F45 /* testshape */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testshape; sourceTree = BUILT_PRODUCTS_DIR; };
 		453774A4120915E3002F0F45 /* testshape.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testshape.c; path = ../../test/testshape.c; sourceTree = SOURCE_ROOT; };
+		AAF02FF41F90089800B9A9FB /* SDL_test_memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_test_memory.c; path = ../../src/test/SDL_test_memory.c; sourceTree = "<group>"; };
 		BBFC088E164C6820003E6A99 /* testgamecontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testgamecontroller.c; path = ../../test/testgamecontroller.c; sourceTree = "<group>"; };
 		BBFC08CD164C6862003E6A99 /* testgamecontroller */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testgamecontroller; sourceTree = BUILT_PRODUCTS_DIR; };
 		BEC566B60761D90300A33029 /* checkkeys */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = checkkeys; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -2212,6 +2214,7 @@
 				DB166D8F16A1D1A500A1396C /* SDL_test_imagePrimitivesBlend.c */,
 				DB166D9016A1D1A500A1396C /* SDL_test_log.c */,
 				DB166D9116A1D1A500A1396C /* SDL_test_md5.c */,
+				AAF02FF41F90089800B9A9FB /* SDL_test_memory.c */,
 				DB166D9216A1D1A500A1396C /* SDL_test_random.c */,
 			);
 			name = SDL_Test;
@@ -3393,6 +3396,7 @@
 				DB166D9E16A1D1A500A1396C /* SDL_test_imagePrimitivesBlend.c in Sources */,
 				DB166D9F16A1D1A500A1396C /* SDL_test_log.c in Sources */,
 				DB166DA016A1D1A500A1396C /* SDL_test_md5.c in Sources */,
+				AAF02FFA1F90092700B9A9FB /* SDL_test_memory.c in Sources */,
 				DB166DA116A1D1A500A1396C /* SDL_test_random.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 14 - 1
configure

@@ -16635,7 +16635,7 @@ fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 
-    for ac_func in malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove wcslen wcscmp strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname getauxval poll
+    for ac_func in malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove wcslen wcscmp strlen strlcpy strlcat _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname getauxval poll
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -16761,6 +16761,19 @@ $as_echo "#define HAVE_SA_SIGACTION 1" >>confdefs.h
 
 fi
 
+
+	    for ac_header in libunwind.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "libunwind.h" "ac_cv_header_libunwind_h" "$ac_includes_default"
+if test "x$ac_cv_header_libunwind_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUNWIND_H 1
+_ACEOF
+
+fi
+
+done
+
 fi
 
 

+ 4 - 1
configure.in

@@ -268,7 +268,7 @@ if test x$enable_libc = xyes; then
         AC_DEFINE(HAVE_MPROTECT, 1, [ ])
         ]),
     )
-    AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove wcslen wcscmp strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname getauxval poll)
+    AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove wcslen wcscmp strlen strlcpy strlcat _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp vsscanf vsnprintf fopen64 fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname getauxval poll)
 
     AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"])
     AC_CHECK_FUNCS(atan atan2 acos asin ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt sqrtf tan tanf)
@@ -277,6 +277,9 @@ if test x$enable_libc = xyes; then
     AC_CHECK_FUNCS(iconv)
 
     AC_CHECK_MEMBER(struct sigaction.sa_sigaction,[AC_DEFINE([HAVE_SA_SIGACTION], 1, [ ])], ,[#include <signal.h>])
+
+	dnl Check for additional non-standard headers
+    AC_CHECK_HEADERS(libunwind.h)
 fi
 
 dnl AC_CHECK_SIZEOF(void*)

+ 1 - 1
include/SDL_config.h.cmake

@@ -72,6 +72,7 @@
 #cmakedefine HAVE_SYS_TYPES_H 1
 #cmakedefine HAVE_WCHAR_H 1
 #cmakedefine HAVE_PTHREAD_NP_H 1
+#cmakedefine HAVE_LIBUNWIND_H 1
 
 /* C library functions */
 #cmakedefine HAVE_MALLOC 1
@@ -99,7 +100,6 @@
 #cmakedefine HAVE_STRLEN 1
 #cmakedefine HAVE_STRLCPY 1
 #cmakedefine HAVE_STRLCAT 1
-#cmakedefine HAVE_STRDUP 1
 #cmakedefine HAVE__STRREV 1
 #cmakedefine HAVE__STRUPR 1
 #cmakedefine HAVE__STRLWR 1

+ 1 - 1
include/SDL_config.h.in

@@ -75,6 +75,7 @@
 #undef HAVE_SYS_TYPES_H
 #undef HAVE_WCHAR_H
 #undef HAVE_PTHREAD_NP_H
+#undef HAVE_LIBUNWIND_H
 
 /* C library functions */
 #undef HAVE_MALLOC
@@ -102,7 +103,6 @@
 #undef HAVE_STRLEN
 #undef HAVE_STRLCPY
 #undef HAVE_STRLCAT
-#undef HAVE_STRDUP
 #undef HAVE__STRREV
 #undef HAVE__STRUPR
 #undef HAVE__STRLWR

+ 1 - 1
include/SDL_config_android.h

@@ -46,6 +46,7 @@
 #define HAVE_STDIO_H    1
 #define HAVE_STRING_H   1
 #define HAVE_SYS_TYPES_H    1
+#define HAVE_LIBUNWIND_H    1
 
 /* C library functions */
 #define HAVE_MALLOC 1
@@ -68,7 +69,6 @@
 #define HAVE_STRLEN 1
 #define HAVE_STRLCPY    1
 #define HAVE_STRLCAT    1
-#define HAVE_STRDUP 1
 #define HAVE_STRCHR 1
 #define HAVE_STRRCHR    1
 #define HAVE_STRSTR 1

+ 1 - 1
include/SDL_config_iphoneos.h

@@ -44,6 +44,7 @@
 #define HAVE_STDIO_H    1
 #define HAVE_STRING_H   1
 #define HAVE_SYS_TYPES_H    1
+#define HAVE_LIBUNWIND_H    1
 
 /* C library functions */
 #define HAVE_MALLOC 1
@@ -66,7 +67,6 @@
 #define HAVE_STRLEN 1
 #define HAVE_STRLCPY    1
 #define HAVE_STRLCAT    1
-#define HAVE_STRDUP 1
 #define HAVE_STRCHR 1
 #define HAVE_STRRCHR    1
 #define HAVE_STRSTR 1

+ 1 - 1
include/SDL_config_macosx.h

@@ -49,6 +49,7 @@
 #define HAVE_STDIO_H    1
 #define HAVE_STRING_H   1
 #define HAVE_SYS_TYPES_H    1
+#define HAVE_LIBUNWIND_H    1
 
 /* C library functions */
 #define HAVE_MALLOC 1
@@ -70,7 +71,6 @@
 #define HAVE_STRLEN 1
 #define HAVE_STRLCPY    1
 #define HAVE_STRLCAT    1
-#define HAVE_STRDUP 1
 #define HAVE_STRCHR 1
 #define HAVE_STRRCHR    1
 #define HAVE_STRSTR 1

+ 0 - 1
include/SDL_config_pandora.h

@@ -70,7 +70,6 @@
 #define HAVE_MEMCPY 1
 #define HAVE_MEMMOVE 1
 #define HAVE_STRLEN 1
-#define HAVE_STRDUP 1
 #define HAVE_STRCHR 1
 #define HAVE_STRRCHR 1
 #define HAVE_STRSTR 1

+ 0 - 1
include/SDL_config_psp.h

@@ -66,7 +66,6 @@
 #define HAVE_STRLEN 1
 #define HAVE_STRLCPY    1
 #define HAVE_STRLCAT    1
-#define HAVE_STRDUP 1
 #define HAVE_STRCHR 1
 #define HAVE_STRRCHR    1
 #define HAVE_STRSTR 1

+ 0 - 1
include/SDL_config_wiz.h

@@ -64,7 +64,6 @@
 #define HAVE_MEMCPY 1
 #define HAVE_MEMMOVE 1
 #define HAVE_STRLEN 1
-#define HAVE_STRDUP 1
 #define HAVE_STRCHR 1
 #define HAVE_STRRCHR 1
 #define HAVE_STRSTR 1

+ 31 - 0
include/SDL_stdinc.h

@@ -347,6 +347,37 @@ extern DECLSPEC void *SDLCALL SDL_calloc(size_t nmemb, size_t size);
 extern DECLSPEC void *SDLCALL SDL_realloc(void *mem, size_t size);
 extern DECLSPEC void SDLCALL SDL_free(void *mem);
 
+typedef void *(SDLCALL *SDL_malloc_func)(size_t size);
+typedef void *(SDLCALL *SDL_calloc_func)(size_t nmemb, size_t size);
+typedef void *(SDLCALL *SDL_realloc_func)(void *mem, size_t size);
+typedef void (SDLCALL *SDL_free_func)(void *mem);
+
+/**
+ *  \brief Get the current set of SDL memory functions
+ */
+extern DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_func,
+                                                    SDL_calloc_func *calloc_func,
+                                                    SDL_realloc_func *realloc_func,
+                                                    SDL_free_func *free_func);
+
+/**
+ *  \brief Replace SDL's memory allocation functions with a custom set
+ *
+ *  \note If you are replacing SDL's memory functions, you should call
+ *        SDL_GetNumAllocations() and be very careful if it returns non-zero.
+ *        That means that your free function will be called with memory
+ *        allocated by the previous memory allocation functions.
+ */
+extern DECLSPEC int SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_func,
+                                                   SDL_calloc_func calloc_func,
+                                                   SDL_realloc_func realloc_func,
+                                                   SDL_free_func free_func);
+
+/**
+ *  \brief Get the number of outstanding (unfreed) allocations
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAllocations();
+
 extern DECLSPEC char *SDLCALL SDL_getenv(const char *name);
 extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite);
 

+ 7 - 6
include/SDL_test.h

@@ -31,17 +31,18 @@
 #define SDL_test_h_
 
 #include "SDL.h"
+#include "SDL_test_assert.h"
 #include "SDL_test_common.h"
+#include "SDL_test_compare.h"
+#include "SDL_test_crc32.h"
 #include "SDL_test_font.h"
-#include "SDL_test_random.h"
 #include "SDL_test_fuzzer.h"
-#include "SDL_test_crc32.h"
-#include "SDL_test_md5.h"
-#include "SDL_test_log.h"
-#include "SDL_test_assert.h"
 #include "SDL_test_harness.h"
 #include "SDL_test_images.h"
-#include "SDL_test_compare.h"
+#include "SDL_test_log.h"
+#include "SDL_test_md5.h"
+#include "SDL_test_memory.h"
+#include "SDL_test_random.h"
 
 #include "begin_code.h"
 /* Set up for C function definitions, even when using C++ */

+ 1 - 1
include/SDL_test_crc32.h

@@ -93,7 +93,7 @@ extern "C" {
  * \returns 0 for OK, -1 on error
  *
  */
-int SDLTest_crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
+int SDLTest_Crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32);
 
 /* Same routine broken down into three steps */
 int SDLTest_Crc32CalcStart(SDLTest_Crc32Context * crcContext, CrcUint32 *crc32);

+ 63 - 0
include/SDL_test_memory.h

@@ -0,0 +1,63 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_test_memory.h
+ *
+ *  Include file for SDL test framework.
+ *
+ *  This code is a part of the SDL2_test library, not the main SDL library.
+ */
+
+#ifndef SDL_test_memory_h_
+#define SDL_test_memory_h_
+
+#include "begin_code.h"
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief Start tracking SDL memory allocations
+ * 
+ * \note This should be called before any other SDL functions for complete tracking coverage
+ */
+int SDLTest_TrackAllocations();
+
+/**
+ * \brief Print a log of any outstanding allocations
+ *
+ * \note This can be called after SDL_Quit()
+ */
+void SDLTest_LogAllocations();
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* SDL_test_memory_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 3 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -637,3 +637,6 @@
 #define SDL_Vulkan_GetDrawableSize SDL_Vulkan_GetDrawableSize_REAL
 #define SDL_LockJoysticks SDL_LockJoysticks_REAL
 #define SDL_UnlockJoysticks SDL_UnlockJoysticks_REAL
+#define SDL_GetMemoryFunctions SDL_GetMemoryFunctions_REAL
+#define SDL_SetMemoryFunctions SDL_SetMemoryFunctions_REAL
+#define SDL_GetNumAllocations SDL_GetNumAllocations_REAL

+ 3 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -671,3 +671,6 @@ SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b,
 SDL_DYNAPI_PROC(void,SDL_Vulkan_GetDrawableSize,(SDL_Window *a, int *b, int *c),(a,b,c),)
 SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),)
 SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),)
+SDL_DYNAPI_PROC(void,SDL_GetMemoryFunctions,(SDL_malloc_func *a, SDL_calloc_func *b, SDL_realloc_func *c, SDL_free_func *d),(a,b,c,d),)
+SDL_DYNAPI_PROC(int,SDL_SetMemoryFunctions,(SDL_malloc_func a, SDL_calloc_func b, SDL_realloc_func c, SDL_free_func d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(int,SDL_GetNumAllocations,(void),(),return)

+ 137 - 35
src/stdlib/SDL_malloc.c

@@ -26,39 +26,11 @@
 #include "../SDL_internal.h"
 
 /* This file contains portable memory management functions for SDL */
-
 #include "SDL_stdinc.h"
+#include "SDL_atomic.h"
+#include "SDL_error.h"
 
-#if defined(HAVE_MALLOC)
-
-void *SDL_malloc(size_t size)
-{
-    if (!size) {
-        return malloc(1);
-    }
-    return malloc(size);
-}
-
-void *SDL_calloc(size_t nmemb, size_t size)
-{
-    if (!size || !nmemb) {
-        return calloc(1,1);
-    }
-    return calloc(nmemb, size);
-}
-
-void *SDL_realloc(void *ptr, size_t size)
-{
-    return realloc(ptr, size);
-}
-
-void SDL_free(void *ptr)
-{
-    free(ptr);
-}
-
-#else  /* the rest of this is a LOT of tapdancing to implement malloc. :) */
-
+#ifndef HAVE_MALLOC
 #define LACKS_SYS_TYPES_H
 #define LACKS_STDIO_H
 #define LACKS_STRINGS_H
@@ -66,6 +38,7 @@ void SDL_free(void *ptr)
 #define LACKS_STDLIB_H
 #define ABORT
 #define USE_LOCKS 1
+#define USE_DL_PREFIX
 
 /*
   This is a version (aka dlmalloc) of malloc/free/realloc written by
@@ -642,12 +615,12 @@ DEFAULT_MMAP_THRESHOLD       default: 256K
 #define MALLINFO_FIELD_TYPE size_t
 #endif /* MALLINFO_FIELD_TYPE */
 
+#ifndef memset
 #define memset  SDL_memset
+#endif
+#ifndef memcpy
 #define memcpy  SDL_memcpy
-#define malloc  SDL_malloc
-#define calloc  SDL_calloc
-#define realloc SDL_realloc
-#define free    SDL_free
+#endif
 
 /*
   mallopt tuning options.  SVID/XPG defines four standard parameter
@@ -5271,4 +5244,133 @@ History:
 
 #endif /* !HAVE_MALLOC */
 
+#ifdef HAVE_MALLOC
+#define real_malloc malloc
+#define real_calloc calloc
+#define real_realloc realloc
+#define real_free free
+#else
+#define real_malloc dlmalloc
+#define real_calloc dlcalloc
+#define real_realloc dlrealloc
+#define real_free dlfree
+#endif
+
+/* Memory functions used by SDL that can be replaced by the application */
+static struct
+{
+    SDL_malloc_func malloc_func;
+    SDL_calloc_func calloc_func;
+    SDL_realloc_func realloc_func;
+    SDL_free_func free_func;
+    SDL_atomic_t num_allocations;
+} s_mem = {
+    real_malloc, real_calloc, real_realloc, real_free, { 0 }
+};
+
+void SDL_GetMemoryFunctions(SDL_malloc_func *malloc_func,
+                            SDL_calloc_func *calloc_func,
+                            SDL_realloc_func *realloc_func,
+                            SDL_free_func *free_func)
+{
+    if (malloc_func) {
+        *malloc_func = s_mem.malloc_func;
+    }
+    if (calloc_func) {
+        *calloc_func = s_mem.calloc_func;
+    }
+    if (realloc_func) {
+        *realloc_func = s_mem.realloc_func;
+    }
+    if (free_func) {
+        *free_func = s_mem.free_func;
+    }
+}
+
+int SDL_SetMemoryFunctions(SDL_malloc_func malloc_func,
+                           SDL_calloc_func calloc_func,
+                           SDL_realloc_func realloc_func,
+                           SDL_free_func free_func)
+{
+    if (!malloc_func) {
+        return SDL_InvalidParamError("malloc_func");
+    }
+    if (!calloc_func) {
+        return SDL_InvalidParamError("calloc_func");
+    }
+    if (!realloc_func) {
+        return SDL_InvalidParamError("realloc_func");
+    }
+    if (!free_func) {
+        return SDL_InvalidParamError("free_func");
+    }
+
+    s_mem.malloc_func = malloc_func;
+    s_mem.calloc_func = calloc_func;
+    s_mem.realloc_func = realloc_func;
+    s_mem.free_func = free_func;
+    return 0;
+}
+
+int SDL_GetNumAllocations()
+{
+    return SDL_AtomicGet(&s_mem.num_allocations);
+}
+
+void *SDL_malloc(size_t size)
+{
+    void *mem;
+
+    if (!size) {
+        size = 1;
+    }
+
+    mem = s_mem.malloc_func(size);
+    if (mem) {
+        SDL_AtomicIncRef(&s_mem.num_allocations);
+    }
+    return mem;
+}
+
+void *SDL_calloc(size_t nmemb, size_t size)
+{
+    void *mem;
+
+    if (!nmemb || !size) {
+        nmemb = 1;
+        size = 1;
+    }
+
+    mem = s_mem.calloc_func(nmemb, size);
+    if (mem) {
+        SDL_AtomicIncRef(&s_mem.num_allocations);
+    }
+    return mem;
+}
+
+void *SDL_realloc(void *ptr, size_t size)
+{
+    void *mem;
+
+    if (!ptr && !size) {
+        size = 1;
+    }
+
+    mem = s_mem.realloc_func(ptr, size);
+    if (mem && !ptr) {
+        SDL_AtomicIncRef(&s_mem.num_allocations);
+    }
+    return mem;
+}
+
+void SDL_free(void *ptr)
+{
+    if (!ptr) {
+        return;
+    }
+
+    s_mem.free_func(ptr);
+    SDL_AtomicDecRef(&s_mem.num_allocations);
+}
+
 /* vi: set ts=4 sw=4 expandtab: */

+ 0 - 4
src/stdlib/SDL_string.c

@@ -561,16 +561,12 @@ SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen)
 char *
 SDL_strdup(const char *string)
 {
-#if defined(HAVE_STRDUP)
-    return strdup(string);
-#else
     size_t len = SDL_strlen(string) + 1;
     char *newstr = SDL_malloc(len);
     if (newstr) {
         SDL_strlcpy(newstr, string, len);
     }
     return newstr;
-#endif /* HAVE_STRDUP */
 }
 
 char *

+ 21 - 5
src/test/SDL_test_common.c

@@ -47,7 +47,18 @@ static void SDL_snprintfcat(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL
 SDLTest_CommonState *
 SDLTest_CommonCreateState(char **argv, Uint32 flags)
 {
-    SDLTest_CommonState *state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
+    int i;
+    SDLTest_CommonState *state;
+
+    /* Do this first so we catch all allocations */
+    for (i = 1; argv[i]; ++i) {
+        if (SDL_strcasecmp(argv[i], "--trackmem") == 0) {
+            SDLTest_TrackAllocations();
+            break;
+        }
+    }
+
+    state = (SDLTest_CommonState *)SDL_calloc(1, sizeof(*state));
     if (!state) {
         SDL_OutOfMemory();
         return NULL;
@@ -447,6 +458,10 @@ SDLTest_CommonArg(SDLTest_CommonState * state, int index)
         state->audiospec.samples = (Uint16) SDL_atoi(argv[index]);
         return 2;
     }
+    if (SDL_strcasecmp(argv[index], "--trackmem") == 0) {
+        /* Already handled in SDLTest_CommonCreateState() */
+        return 1;
+    }
     if ((SDL_strcasecmp(argv[index], "-h") == 0)
         || (SDL_strcasecmp(argv[index], "--help") == 0)) {
         /* Print the usage message */
@@ -464,13 +479,13 @@ SDLTest_CommonUsage(SDLTest_CommonState * state)
 {
     switch (state->flags & (SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {
     case SDL_INIT_VIDEO:
-        return VIDEO_USAGE;
+        return "[--trackmem] " VIDEO_USAGE;
     case SDL_INIT_AUDIO:
-        return AUDIO_USAGE;
+        return "[--trackmem] " AUDIO_USAGE;
     case (SDL_INIT_VIDEO | SDL_INIT_AUDIO):
-        return VIDEO_USAGE " " AUDIO_USAGE;
+        return "[--trackmem] " VIDEO_USAGE " " AUDIO_USAGE;
     default:
-        return "";
+        return "[--trackmem]";
     }
 }
 
@@ -1762,6 +1777,7 @@ SDLTest_CommonQuit(SDLTest_CommonState * state)
     }
     SDL_free(state);
     SDL_Quit();
+    SDLTest_LogAllocations();
 }
 
 /* vi: set ts=4 sw=4 expandtab: */

+ 0 - 2
src/test/SDL_test_crc32.c

@@ -69,7 +69,6 @@ int SDLTest_Crc32Init(SDLTest_Crc32Context *crcContext)
 }
 
 /* Complete CRC32 calculation on a memory block */
-/* un-used
 int SDLTest_Crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32)
 {
   if (SDLTest_Crc32CalcStart(crcContext,crc32)) {
@@ -86,7 +85,6 @@ int SDLTest_Crc32Calc(SDLTest_Crc32Context * crcContext, CrcUint8 *inBuf, CrcUin
 
   return 0;
 }
-*/
 
 /* Start crc calculation */