我正在尝试使用类的私有变量来制作SDL窗口。为了从私有变量创建一个窗口,我尝试使用 getter 和 setter。但是,我收到此错误:
ShootemUp.exe 中的 0x00007FFBF93852D7 (SDL2.dll) 处抛出异常:0xC0000005:读取位置 0x0000000100000008 时发生访问冲突。
我该如何解决这个问题?
这是我的代码:
#include "common.h"
void Init() {
int windowFlag, rendererFlag;
rendererFlag = SDL_RENDERER_ACCELERATED;
windowFlag = 0;
App application;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "Couldn't intialize SDL! Error:" << SDL_GetError;
exit(-1);
}
else {
SDL_Window* window = NULL;
window = SDL_CreateWindow("Shoot em' up", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
application.setWindow(window);
SDL_DestroyWindow(window);
if (!application.getWindow()) {
std::cout << "Window not intialized! Error:" << SDL_GetError;
exit(-1);
}
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
SDL_Renderer* renderer = NULL;
renderer = SDL_CreateRenderer(application.getWindow(), -1, rendererFlag);
application.setRenderer(renderer);
if (!application.getRenderer()) {
std::cout << "Renderer not intialized! Error:" << SDL_Error;
exit(-1);
}
}
}
我在这一行收到错误:
renderer = SDL_CreateRenderer(application.getWindow(), -1, rendererFlag);
我尝试使用私有窗口变量创建渲染器。
这是带有 getter 和 setter 的文件:
#include "Common.h"
void App::setWindow(SDL_Window* window) {
this->window = window;
}
void App::setRenderer(SDL_Renderer* renderer) {
this->renderer = renderer;
}
SDL_Window* App::getWindow() {
return window;
}
SDL_Renderer* App::getRenderer() {
return renderer;
}
您在将
SDL_Window
对象交给您的 application
对象后将其销毁,从而留下一个 悬空指针,然后 App::getWindow()
随后返回:
SDL_Window* window = NULL;
window = SDL_CreateWindow(...);
application.setWindow(window); // <-- sets App::window, OK here
SDL_DestroyWindow(window); // <-- now App::window is dangling!
...
renderer = SDL_CreateRenderer(application.getWindow(), ...); // <-- AV using invalid App::window!
当您将
SDL_Window
对象传递给 SDL_CreateRenderer()
时,它就不再有效,这就是 AV 发生的原因。
您的
if (!application.getWindow())
检查无法检测到这种情况,因为存储在 SDL_Window*
对象内的 application
指针不是 nullptr
,它仍然指向您销毁的内存。为了避免这种情况,您必须在拨打 application.setWindow(nullptr)
之后再拨打 SDL_DestroyWindow()
。
因此,真正的解决方法是在某些东西仍在使用
SDL_Window
对象时不要销毁它! 对 SDL_DestroyWindow()
(和 SDL_DestroyRenderer()
,此代码中缺少)的调用需要稍后在代码中完成,在 application
对象使用 SDL_Window
(和 SDL_Renderer
)完成之后,例如在 App::~App()
析构函数中(或者至少在 application
对象被销毁之后)。