选择PixelFormat 访问冲突读取位置
Posted
技术标签:
【中文标题】选择PixelFormat 访问冲突读取位置【英文标题】:ChoosePixelFormat Access violation reading location 【发布时间】:2017-02-20 09:35:29 【问题描述】:我正在尝试创建一个简单的 OpenGL 上下文,但程序在 ChoosePixelFormat 上崩溃并显示错误“OpenGL.exe 中 0x779CE0E6 (ntdll.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0x00000044。”这个相同的代码过去可以工作一段时间,但由于某种原因不再工作了。我尝试更新我的图形驱动程序无济于事。如果重要的话,我有 64 位 Windows 7 Home Premium、GeForce 570 和 Intel Core i7-2600 3,40 GHz。
这是我按执行顺序使用到崩溃的代码:
GLEngine gl(WndProc); //WndProc just calls DefWindowProc
- calls ->
GLEngine::GLEngine(WNDPROC wndproc) //Initialize class
hRC = NULL;
hDC = NULL;
hWnd = NULL;
fullscreen = false;
active = false;
proc = wndproc;
itemsLength = 0;
currentActive = this;
success = true;
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow)
gl.CreateGL2Window("Test", 1300, 900, 8, false, true);
- calls ->
bool GLEngine::CreateGL2Window(char* title, int width, int height, bool internalflag)
GLuint pixelFormat;
WNDCLASSEX wc;
DWORD dwExStyle;
DWORD dwStyle;
RECT windowRect;
windowRect.left = (long)0;
windowRect.right = (long)width;
windowRect.top = (long)0;
windowRect.bottom = (long)height;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance; //hInstance is NULL here, should it be something else?
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = _T("OpenGL");
wc.hIconSm = NULL;
if(!RegisterClassEx(&wc))
MessageBox(NULL, _T("Failed To Register The Window Class."), _T("ERROR"), MB_OK | MB_ICONEXCLAMATION);
return false;
hInstance = wc.hInstance; //hInstance isn't NULL anymore
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
AdjustWindowRectEx(&windowRect, dwStyle, false, dwExStyle);
if(!(hWnd = CreateWindowEx(dwExStyle, _T("OpenGL"),
(wchar_t*)title,
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dwStyle,
0, 0,
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top,
NULL,
NULL,
hInstance,
NULL)))
DestroyGLWindow();
MessageBox(NULL, _T("Window Creation Error."), _T("ERROR"), MB_OK | MB_ICONEXCLAMATION);
return false;
if(!(hDC = GetDC(hWnd)))
DestroyGLWindow();
MessageBox(NULL, _T("Can't Create A GL Device Context."), _T("ERROR"), MB_OK | MB_ICONEXCLAMATION);
return false;
PIXELFORMATDESCRIPTOR pfd2 = sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
32,
8,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
;
if(!(pixelFormat = ChoosePixelFormat(hDC, &pfd2))
GLEngine 在一个 dll 中。没关系,但信息不会受到伤害。
【问题讨论】:
刚刚测试了您的代码,不会对我抛出任何错误(最后一个 if 语句中缺少)
除外。
这是一个简单的空指针异常。可能会在尝试访问 hDC 成员时死掉。所以它看起来 像调用ChoosePixelFormat() 但它还没有完全到达那里。从堆栈跟踪中应该很明显,您会看到 CreateGL2Window,但看不到 ChoosePixelFormat。和调试器,设置断点并检查this
。 gl
是如何被破坏的很难看出,也许你在掩盖它。
@HansPassant 我在 ChoosePixelFormat 行设置了一个断点,它在该行崩溃。还检查了 hDC 或 &pfd2 是否为空。调用堆栈只是将不同的 dll 显示为灰色。因为我没有它们的符号。 (ntdll.dll 和 appinit_dll.dll)
@BDL 你有什么显卡/驱动程序?
【参考方案1】:
您是否使用 GetProcAddress 获得函数地址?错误的驱动程序也可能导致崩溃。 ChoosePixelFormat 可以在驱动端实现和导出,也可以不导出,需要使用系统程序。导出的一个可能会或可能不会填充描述符结构,具体取决于实现,因此您需要调用 DescribePixelFormat。
【讨论】:
不会出现“访问冲突执行位置....”之类的错误吗? @BDL 访问冲突是典型的驱动问题。但通常是 UB,任何事情都可能发生 @Swift:ChoosePixelFormat 是一个 GDI 函数,从 gdi32.dll 导出。 OpenGL ICD 不应有任何业务干预其入口点。 对不起,如果我不清楚。如果函数指针地址未正确加载,则错误消息会抱怨“访问冲突执行位置”,而当函数尝试时它会声明“访问冲突读取位置”访问无效地址的数据。正如 datenwolf 所说:ChoosePixelFormat 根本不是函数指针。 @datenwolf 这个。我实际上是在尝试创建上下文以加载 wgl 函数。 hDC 和 pfd2 似乎也有效。以上是关于选择PixelFormat 访问冲突读取位置的主要内容,如果未能解决你的问题,请参考以下文章