SDL2 在 window 调整大小时崩溃
SDL2 crashes on window resize
我在我的 C++ 游戏中使用 SDL2,我正在尝试实现即时进入和退出全屏的能力(老实说,我只是最大化 window ).问题是,每次我调用 SDL_MaximizeWindow
或 SDL_RestoreWindow
,它都会立即因段错误而崩溃,转储堆栈并退出。请注意,当我用鼠标手动调整 window 大小时,它也会执行此操作。
这里有一些有用的数据:
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);
}
游戏在每次手动调整大小和每次调用 toggleFullscreen
时崩溃。我正在 Windows 上通过 mingw-w64 和 Msys2 使用 g++ 进行编译,这里是堆栈转储。
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
如果我做错了什么,请告诉我,提前致谢!
编辑:这是一些崩溃的代码。
#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;
}
编辑 2:GDB 告诉我有关崩溃的信息 (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
test.c 的第 23 行是:
SDL_RenderCopy(sdlRenderer, s, NULL, NULL);
好吧,经过大量研究,我发现了一个 GitHub 问题,有人在 1 月份的某个时候在他们的游戏中遇到了同样的问题,并且问题 (https://github.com/Attnam/ivan/pull/135) pointed me all the way to this thread (https://forums.libsdl.org/viewtopic.php?t=11913),然后告诉我提示 SDL2 使用 OpenGL 渲染器而不是 D3D,这对我有用。
所以基本上,问题是当使用带有标志 SDL_TEXTUREACCESS_STREAMING
的 SDL_Texture
时,调整 window 的大小会破坏纹理并且不会再次创建它,因为 D3D 不会'使用它(或其他东西)时不要检查 NULL 指针。显然它是唯一有此问题的渲染器,因此在您的程序中使用以下内容将修复它:
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
开发人员说它应该在下一个 SDL2 版本(即 2.0.5)中修复,但出于某种原因我无法用它编译我的游戏。不过,这是一个全新的问题,目前已解决此问题。
我在我的 C++ 游戏中使用 SDL2,我正在尝试实现即时进入和退出全屏的能力(老实说,我只是最大化 window ).问题是,每次我调用 SDL_MaximizeWindow
或 SDL_RestoreWindow
,它都会立即因段错误而崩溃,转储堆栈并退出。请注意,当我用鼠标手动调整 window 大小时,它也会执行此操作。
这里有一些有用的数据:
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);
}
游戏在每次手动调整大小和每次调用 toggleFullscreen
时崩溃。我正在 Windows 上通过 mingw-w64 和 Msys2 使用 g++ 进行编译,这里是堆栈转储。
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
如果我做错了什么,请告诉我,提前致谢!
编辑:这是一些崩溃的代码。
#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;
}
编辑 2:GDB 告诉我有关崩溃的信息 (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
test.c 的第 23 行是:
SDL_RenderCopy(sdlRenderer, s, NULL, NULL);
好吧,经过大量研究,我发现了一个 GitHub 问题,有人在 1 月份的某个时候在他们的游戏中遇到了同样的问题,并且问题 (https://github.com/Attnam/ivan/pull/135) pointed me all the way to this thread (https://forums.libsdl.org/viewtopic.php?t=11913),然后告诉我提示 SDL2 使用 OpenGL 渲染器而不是 D3D,这对我有用。
所以基本上,问题是当使用带有标志 SDL_TEXTUREACCESS_STREAMING
的 SDL_Texture
时,调整 window 的大小会破坏纹理并且不会再次创建它,因为 D3D 不会'使用它(或其他东西)时不要检查 NULL 指针。显然它是唯一有此问题的渲染器,因此在您的程序中使用以下内容将修复它:
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
开发人员说它应该在下一个 SDL2 版本(即 2.0.5)中修复,但出于某种原因我无法用它编译我的游戏。不过,这是一个全新的问题,目前已解决此问题。