选择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。和调试器,设置断点并检查thisgl 是如何被破坏的很难看出,也许你在掩盖它。 @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 访问冲突读取位置的主要内容,如果未能解决你的问题,请参考以下文章

访问dll方法时访问冲突读取位置

glDrawPixels 访问冲突读取位置

**** 访问冲突读取位置处未处理的异常 *******

访问冲突读取位置0x00000002 [关闭]

使用 ReadFile 时访问冲突读取位置

访问冲突读取位置 0xcccccccc