Skip to content

Commit

Permalink
Small stack allocations fall back to malloc if they're unexpectedly l…
Browse files Browse the repository at this point in the history
…arge.
  • Loading branch information
icculus committed Oct 23, 2018
1 parent eedf2c9 commit b262b0e
Show file tree
Hide file tree
Showing 19 changed files with 84 additions and 52 deletions.
1 change: 1 addition & 0 deletions src/SDL_assert.c
Expand Up @@ -178,6 +178,7 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)

(void) userdata; /* unused in default handler. */

/* !!! FIXME: why is this using SDL_stack_alloc and not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
if (!message) {
/* Uh oh, we're in real trouble now... */
Expand Down
4 changes: 4 additions & 0 deletions src/SDL_internal.h
Expand Up @@ -35,6 +35,10 @@
#define SDL_VARIABLE_LENGTH_ARRAY
#endif

#define SDL_MAX_SMALL_ALLOC_STACKSIZE 128
#define SDL_small_alloc(type, count, pisstack) ( (*(pisstack) = ((sizeof(type)*(count)) < SDL_MAX_SMALL_ALLOC_STACKSIZE)), (*(pisstack) ? SDL_stack_alloc(type, count) : (type*)SDL_malloc(sizeof(type)*(count))) )
#define SDL_small_free(ptr, isstack) if ((isstack)) { SDL_stack_free(ptr); } else { SDL_free(ptr); }

#include "dynapi/SDL_dynapi.h"

#if SDL_DYNAMIC_API
Expand Down
8 changes: 5 additions & 3 deletions src/SDL_log.c
Expand Up @@ -282,6 +282,7 @@ SDL_LogMessageV(int category, SDL_LogPriority priority, const char *fmt, va_list
return;
}

/* !!! FIXME: why not just "char message[SDL_MAX_LOG_MESSAGE];" ? */
message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
if (!message) {
return;
Expand Down Expand Up @@ -321,6 +322,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
char *output;
size_t length;
LPTSTR tstr;
SDL_bool isstack;

#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
BOOL attachResult;
Expand Down Expand Up @@ -364,7 +366,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */

length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
output = SDL_stack_alloc(char, length);
output = SDL_small_alloc(char, length, &isstack);
SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
tstr = WIN_UTF8ToString(output);

Expand All @@ -389,7 +391,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */

SDL_free(tstr);
SDL_stack_free(output);
SDL_small_free(output, isstack);
}
#elif defined(__ANDROID__)
{
Expand All @@ -404,7 +406,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
extern void SDL_NSLog(const char *text);
{
char *text;

/* !!! FIXME: why not just "char text[SDL_MAX_LOG_MESSAGE];" ? */
text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
if (text) {
SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message);
Expand Down
5 changes: 3 additions & 2 deletions src/core/android/SDL_android.c
Expand Up @@ -466,10 +466,11 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv* env, jclass cls,
int argc;
int len;
char **argv;
SDL_bool isstack;

/* Prepare the arguments. */
len = (*env)->GetArrayLength(env, array);
argv = SDL_stack_alloc(char*, 1 + len + 1);
argv = SDL_small_alloc(char*, 1 + len + 1, &isstack); /* !!! FIXME: check for NULL */
argc = 0;
/* Use the name "app_process" so PHYSFS_platformCalcBaseDir() works.
https://bitbucket.org/MartinFelis/love-android-sdl2/issue/23/release-build-crash-on-start
Expand Down Expand Up @@ -502,7 +503,7 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv* env, jclass cls,
for (i = 0; i < argc; ++i) {
SDL_free(argv[i]);
}
SDL_stack_free(argv);
SDL_small_free(argv, isstack);

} else {
__android_log_print(ANDROID_LOG_ERROR, "SDL", "nativeRunMain(): Couldn't find function %s in library %s", function_name, library_file);
Expand Down
1 change: 1 addition & 0 deletions src/file/SDL_rwops.c
Expand Up @@ -528,6 +528,7 @@ SDL_RWFromFile(const char *file, const char *mode)
char *path;
FILE *fp;

/* !!! FIXME: why not just "char path[PATH_MAX];" ? */
path = SDL_stack_alloc(char, PATH_MAX);
if (path) {
SDL_snprintf(path, PATH_MAX, "%s/%s",
Expand Down
5 changes: 3 additions & 2 deletions src/joystick/SDL_gamecontroller.c
Expand Up @@ -203,13 +203,14 @@ static void UpdateEventsForDeviceRemoval()
{
int i, num_events;
SDL_Event *events;
SDL_bool isstack;

num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEADDED);
if (num_events <= 0) {
return;
}

events = SDL_stack_alloc(SDL_Event, num_events);
events = SDL_small_alloc(SDL_Event, num_events, &isstack);
if (!events) {
return;
}
Expand All @@ -220,7 +221,7 @@ static void UpdateEventsForDeviceRemoval()
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);

SDL_stack_free(events);
SDL_small_free(events, isstack);
}

static SDL_bool HasSameOutput(SDL_ExtendedGameControllerBind *a, SDL_ExtendedGameControllerBind *b)
Expand Down
5 changes: 3 additions & 2 deletions src/joystick/SDL_joystick.c
Expand Up @@ -752,13 +752,14 @@ static void UpdateEventsForDeviceRemoval()
{
int i, num_events;
SDL_Event *events;
SDL_bool isstack;

num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
if (num_events <= 0) {
return;
}

events = SDL_stack_alloc(SDL_Event, num_events);
events = SDL_small_alloc(SDL_Event, num_events, &isstack);
if (!events) {
return;
}
Expand All @@ -769,7 +770,7 @@ static void UpdateEventsForDeviceRemoval()
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);

SDL_stack_free(events);
SDL_small_free(events, isstack);
}

void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
Expand Down
5 changes: 3 additions & 2 deletions src/loadso/dlopen/SDL_sysloadso.c
Expand Up @@ -61,12 +61,13 @@ SDL_LoadFunction(void *handle, const char *name)
void *symbol = dlsym(handle, name);
if (symbol == NULL) {
/* append an underscore for platforms that need that. */
SDL_bool isstack;
size_t len = 1 + SDL_strlen(name) + 1;
char *_name = SDL_stack_alloc(char, len);
char *_name = SDL_small_alloc(char, len, &isstack);
_name[0] = '_';
SDL_strlcpy(&_name[1], name, len);
symbol = dlsym(handle, _name);
SDL_stack_free(_name);
SDL_small_free(_name, isstack);
if (symbol == NULL) {
SDL_SetError("Failed loading %s: %s", name,
(const char *) dlerror());
Expand Down
10 changes: 6 additions & 4 deletions src/main/windows/SDL_windows_main.c
Expand Up @@ -131,6 +131,7 @@ main_utf8(int argc, char *argv[])
static int
main_getcmdline()
{
SDL_bool isstack;
char **argv;
int argc;
char *cmdline;
Expand All @@ -150,15 +151,15 @@ main_getcmdline()

/* Parse it into argv and argc */
argc = ParseCommandLine(cmdline, NULL);
argv = SDL_stack_alloc(char *, argc + 1);
argv = SDL_small_alloc(char *, argc + 1, &isstack);
if (argv == NULL) {
return OutOfMemory();
}
ParseCommandLine(cmdline, argv);

retval = main_utf8(argc, argv);

SDL_stack_free(argv);
SDL_small_free(argv, isstack);
SDL_free(cmdline);

return retval;
Expand All @@ -177,8 +178,9 @@ console_ansi_main(int argc, char *argv[])
int
console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
{
SDL_bool isstack;
int retval = 0;
char **argv = SDL_stack_alloc(char*, argc + 1);
char **argv = SDL_small_alloc(char*, argc + 1, &isstack);
int i;

for (i = 0; i < argc; ++i) {
Expand All @@ -189,7 +191,7 @@ console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
retval = main_utf8(argc, argv);

/* !!! FIXME: we are leaking all the elements of argv we allocated. */
SDL_stack_free(argv);
SDL_small_free(argv, isstack);

return retval;
}
Expand Down
25 changes: 15 additions & 10 deletions src/render/SDL_render.c
Expand Up @@ -2176,8 +2176,9 @@ RenderDrawPointsWithRects(SDL_Renderer * renderer,
SDL_FRect *frects;
int i;
int retval = -1;
SDL_bool isstack;

frects = SDL_stack_alloc(SDL_FRect, count);
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
Expand All @@ -2190,7 +2191,7 @@ RenderDrawPointsWithRects(SDL_Renderer * renderer,

retval = QueueCmdFillRects(renderer, frects, count);

SDL_stack_free(frects);
SDL_small_free(frects, isstack);

return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
Expand All @@ -2202,6 +2203,7 @@ SDL_RenderDrawPoints(SDL_Renderer * renderer,
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;

CHECK_RENDERER_MAGIC(renderer, -1);

Expand All @@ -2221,7 +2223,7 @@ SDL_RenderDrawPoints(SDL_Renderer * renderer,
return RenderDrawPointsWithRects(renderer, points, count);
}

fpoints = SDL_stack_alloc(SDL_FPoint, count);
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
Expand All @@ -2232,7 +2234,7 @@ SDL_RenderDrawPoints(SDL_Renderer * renderer,

retval = QueueCmdDrawPoints(renderer, fpoints, count);

SDL_stack_free(fpoints);
SDL_small_free(fpoints, isstack);

return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
Expand All @@ -2258,8 +2260,9 @@ RenderDrawLinesWithRects(SDL_Renderer * renderer,
SDL_FPoint fpoints[2];
int i, nrects = 0;
int retval = 0;
SDL_bool isstack;

frects = SDL_stack_alloc(SDL_FRect, count-1);
frects = SDL_small_alloc(SDL_FRect, count-1, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
Expand Down Expand Up @@ -2295,7 +2298,7 @@ RenderDrawLinesWithRects(SDL_Renderer * renderer,

retval += QueueCmdFillRects(renderer, frects, nrects);

SDL_stack_free(frects);
SDL_small_free(frects, isstack);

if (retval < 0) {
retval = -1;
Expand All @@ -2310,6 +2313,7 @@ SDL_RenderDrawLines(SDL_Renderer * renderer,
SDL_FPoint *fpoints;
int i;
int retval;
SDL_bool isstack;

CHECK_RENDERER_MAGIC(renderer, -1);

Expand All @@ -2329,7 +2333,7 @@ SDL_RenderDrawLines(SDL_Renderer * renderer,
return RenderDrawLinesWithRects(renderer, points, count);
}

fpoints = SDL_stack_alloc(SDL_FPoint, count);
fpoints = SDL_small_alloc(SDL_FPoint, count, &isstack);
if (!fpoints) {
return SDL_OutOfMemory();
}
Expand All @@ -2340,7 +2344,7 @@ SDL_RenderDrawLines(SDL_Renderer * renderer,

retval = QueueCmdDrawLines(renderer, fpoints, count);

SDL_stack_free(fpoints);
SDL_small_free(fpoints, isstack);

return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
Expand Down Expand Up @@ -2426,6 +2430,7 @@ SDL_RenderFillRects(SDL_Renderer * renderer,
SDL_FRect *frects;
int i;
int retval;
SDL_bool isstack;

CHECK_RENDERER_MAGIC(renderer, -1);

Expand All @@ -2441,7 +2446,7 @@ SDL_RenderFillRects(SDL_Renderer * renderer,
return 0;
}

frects = SDL_stack_alloc(SDL_FRect, count);
frects = SDL_small_alloc(SDL_FRect, count, &isstack);
if (!frects) {
return SDL_OutOfMemory();
}
Expand All @@ -2454,7 +2459,7 @@ SDL_RenderFillRects(SDL_Renderer * renderer,

retval = QueueCmdFillRects(renderer, frects, count);

SDL_stack_free(frects);
SDL_small_free(frects, isstack);

return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
}
Expand Down
5 changes: 3 additions & 2 deletions src/render/opengl/SDL_render_gl.c
Expand Up @@ -1348,10 +1348,11 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,

/* Flip the rows to be top-down if necessary */
if (!renderer->target) {
SDL_bool isstack;
length = rect->w * SDL_BYTESPERPIXEL(temp_format);
src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
dst = (Uint8*)temp_pixels;
tmp = SDL_stack_alloc(Uint8, length);
tmp = SDL_small_alloc(Uint8, length, &isstack);
rows = rect->h / 2;
while (rows--) {
SDL_memcpy(tmp, dst, length);
Expand All @@ -1360,7 +1361,7 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
dst += temp_pitch;
src -= temp_pitch;
}
SDL_stack_free(tmp);
SDL_small_free(tmp, isstack);
}

status = SDL_ConvertPixels(rect->w, rect->h,
Expand Down
5 changes: 3 additions & 2 deletions src/render/opengl/SDL_shaders_gl.c
Expand Up @@ -340,19 +340,20 @@ CompileShader(GL_ShaderContext *ctx, GLhandleARB shader, const char *defines, co
ctx->glCompileShaderARB(shader);
ctx->glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
if (status == 0) {
SDL_bool isstack;
GLint length;
char *info;

ctx->glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
info = SDL_stack_alloc(char, length+1);
info = SDL_small_alloc(char, length+1, &isstack);
ctx->glGetInfoLogARB(shader, length, NULL, info);
SDL_LogError(SDL_LOG_CATEGORY_RENDER,
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
#ifdef DEBUG_SHADERS
fprintf(stderr,
"Failed to compile shader:\n%s%s\n%s", defines, source, info);
#endif
SDL_stack_free(info);
SDL_small_free(info, isstack);

return SDL_FALSE;
} else {
Expand Down
5 changes: 3 additions & 2 deletions src/render/opengles/SDL_render_gles.c
Expand Up @@ -972,10 +972,11 @@ GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,

/* Flip the rows to be top-down if necessary */
if (!renderer->target) {
SDL_bool isstack;
length = rect->w * SDL_BYTESPERPIXEL(temp_format);
src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
dst = (Uint8*)temp_pixels;
tmp = SDL_stack_alloc(Uint8, length);
tmp = SDL_small_alloc(Uint8, length, &isstack);
rows = rect->h / 2;
while (rows--) {
SDL_memcpy(tmp, dst, length);
Expand All @@ -984,7 +985,7 @@ GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
dst += temp_pitch;
src -= temp_pitch;
}
SDL_stack_free(tmp);
SDL_small_free(tmp, isstack);
}

status = SDL_ConvertPixels(rect->w, rect->h,
Expand Down

0 comments on commit b262b0e

Please sign in to comment.