Matrefeytontias Matrefeytontias - 1 month ago 19
C++ Question

SDL2 crashes on window resize

I am using SDL2 with my C++ game, and I am trying to implement the ability to go in and out of fullscreen on-the-fly (in all honesty, I'm just maximizing the window). The thing is, every time I call

SDL_MaximizeWindow
or
SDL_RestoreWindow
, it instantly crashes with a segfault, dumps the stack and quits. Note that it also does this when I manually resize the window with the mouse.

Here is some useful data :

void init()
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
SDL_CreateWindowAndRenderer(320 * 2, 240 * 2, SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE, &sdlWindow, &sdlRenderer);
SDL_RenderSetLogicalSize(sdlRenderer, 320, 240);
MAIN_SCREEN = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, 320, 240);
}
void toggleFullscreen()
{
if(SDL_GetWindowFlags(sdlWindow) & SDL_WINDOW_MAXIMIZED)
SDL_RestoreWindow(sdlWindow);
else
SDL_MaximizeWindow(sdlWindow);
}


The game crashes on every manual resize and every call to
toggleFullscreen
. I'm compiling with g++ via mingw-w64 and Msys2 on Windows, and here is the stack dump.

Exception: STATUS_ACCESS_VIOLATION at rip=0006C79976B
rax=0000000000000000 rbx=0000000000000000 rcx=0000000000000000
rdx=0000000002F1BE20 rsi=000000000004DD80 rdi=0000000000046078
r8 =00000000FFFFC66C r9 =00000000FFFFC800 r10=0000000000000001
r11=0000000000000000 r12=00000000FFFFC800 r13=0000000000040010
r14=0000000000000001 r15=000000018021CE41
rbp=0000000000046240 rsp=00000000FFFFC580
program=nKaruga.exe, pid 96868, thread main
cs=0033 ds=002B es=002B fs=0053 gs=002B ss=002B
Stack trace:
Frame Function Args
00000046240 0006C79976B (0006C79B8D4, 0000004DE80, 00000000000, 00000000000)
00000000224 0006C799C6E (00000000002, 00001FF5488, 00000000000, 0018021CE41)
000FFFFC7E0 0006C79A64B (00016362004, 00002F85480, 00000000500, 00000000001)
000FFFFC870 0006C7937D3 (00100414C74, 00600000000, 0000000FFFF, 280802601C0)
000FFFFC870 00100418FBA (00000000000, 00600000000, 00100000000, 00000000000)
000FFFFC900 00100416AD4 (00000040010, 000FFFFCC20, 0018004607A, 000004638EF)
00000040030 0010041DA1A (000FFFFCCC0, 000004638F1, 000FFFFCB48, 00100000068)
000FFFFCCC0 00100425013 (00000000020, FF0700010302FF00, 001800479BE, 00000000000)
000FFFFCCC0 00180047A2F (00000000000, 00000000000, 00000000000, 00000000000)
00000000000 00180045753 (00000000000, 00000000000, 00000000000, 00000000000)
000FFFFFFF0 00180045804 (00000000000, 00000000000, 00000000000, 00000000000)
End of stack trace


Let me know if I'm doing anything wrong, thanks by advance !

EDIT : here's some code that crashes.

#include <SDL.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_Texture *s;
SDL_Event event;
bool cont = true;

SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(320 * 2, 240 * 2, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE, &sdlWindow, &sdlRenderer);
SDL_RenderSetLogicalSize(sdlRenderer, 320, 240);
s = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, 320, 240);

while(cont)
{
SDL_PollEvent(&event);
if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE)
cont = false;

SDL_RenderCopy(sdlRenderer, s, NULL, NULL);
SDL_RenderPresent(sdlRenderer);
}

SDL_DestroyTexture(s);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow(sdlWindow);

return 0;
}


EDIT 2 : GDB tells me this about the crash (gcc -Og -g3) :

#0 0x000000006c79976b in SDL_LogCritical () from /c/Users/###/nKaruga-git/bin/win/SDL2.dll
#1 0x000000006c799c6e in SDL_LogCritical () from /c/Users/###/nKaruga-git/bin/win/SDL2.dll
#2 0x000000006c79a64b in SDL_LogCritical () from /c/Users/###/nKaruga-git/bin/win/SDL2.dll
#3 0x000000006c7937d3 in SDL_LogCritical () from /c/Users/###/nKaruga-git/bin/win/SDL2.dll
#4 0x0000000100401194 in SDL_main (argc=argc@entry=1, argv=argv@entry=0x40010) at test.c:23
#5 0x00000001004019fa in main_utf8 (argv=0x40010, argc=<optimized out>) at ../src/main/windows/SDL_windows_main.c:126
#6 WinMain (hInst=hInst@entry=0x100400000, hPrev=hPrev@entry=0x0, szCmdLine=szCmdLine@entry=0x3c38ef "", sw=<optimized out>) at ../src/main/windows/SDL_windows_main.c:189
#7 0x0000000100401ce3 in main () at /msys_scripts/msys2-runtime/src/msys2-runtime/winsup/cygwin/lib/libcmain.c:37


Line 23 of test.c is :

SDL_RenderCopy(sdlRenderer, s, NULL, NULL);

Answer

Alright, after quite a lot of research, I found a GitHub issue of someone having this same issue in their game somewhen back in January, and the issue (https://github.com/Attnam/ivan/pull/135) pointed me all the way to this thread (https://forums.libsdl.org/viewtopic.php?t=11913), which then tells me to hint SDL2 at using an OpenGL renderer instead of D3D, which did work for me.

So basically, the issue is that when using an SDL_Texture with the flag SDL_TEXTUREACCESS_STREAMING, resizing a window destroys the texture and doesn't create it again because D3D doesn't check for a NULL pointer when working with it (or something). Apparently it's the only renderer with this issue, so using the following in your program will fix it :

SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");

The devs say it should be fixed in the next SDL2 release (that would be 2.0.5) but for some reason I can't compile my game with it. That's a whole new issue though, for now this one is fixed.