wglCreateContextAttribsARB在x64平台下的调试模式下崩溃

wglCreateContextAttribsARB crashes in debug mode, under x64 platform

本文关键字:调试 模式 崩溃 wglCreateContextAttribsARB x64 平台      更新时间:2023-10-16

我在Visual Studio 2015下调试64位应用程序时遇到问题。当我将它切换到调试模式时,它会在创建窗口时崩溃。这在32位模式下没有发生;

以下是经过编辑的窗口初始化代码:

int indexPF;
WNDCLASS WinClass;
WinClass.style = CS_OWNDC | CS_PARENTDC;
WinClass.lpfnWndProc = WndProc;
WinClass.cbClsExtra = 0;
WinClass.cbWndExtra = 0;
WinClass.hInstance = hInstance;
WinClass.hIcon = LoadIcon(NULL, IDC_ICON);
WinClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WinClass.hbrBackground = (HBRUSH)GetStockObject(5);
WinClass.lpszMenuName = NULL;
WinClass.lpszClassName = "N2";
if (!RegisterClass(&WinClass))
{
    ...report error and terminate...
}
Logger::Inst() << " ~RegisterClass;" << endl;
//CREATE WINDOW
if (fullScreen)
{
    if ((hwnd = CreateWindowEx(WS_EX_LEFT, "N2", "N2",
        WS_POPUP,
        0, 0, width, height,
        NULL, NULL, hInstance, NULL)) == 0)
    {
        ...report error and terminate...
    }
}
else
{
    if ((hwnd = CreateWindowEx(WS_EX_LEFT, "N2", "N2",
        WS_OVERLAPPEDWINDOW,
        0, 0, width, height,
        NULL, NULL, hInstance, NULL)) == 0)
    {
        ...report error and terminate...
    }
}
Logger::Inst() << " ~CreateWindow;" << endl;
//PFD SETUP
PIXELFORMATDESCRIPTOR pfd =
{
    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,
    24,
    8, 0, PFD_MAIN_PLANE, 0, 0, 0x00FF00FF, 0
};
//HDC
if ((hdc = GetDC(hwnd)) == NULL)
{
    ...report error and terminate...
}
Logger::Inst() << " ~GotHDC;" << endl;
//SET PIXEL FORMAT
indexPF = ChoosePixelFormat(hdc, &pfd);
if (!indexPF)
{
    ...report error and terminate...
}
if (!SetPixelFormat(hdc, indexPF, &pfd))
{
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
    indexPF = ChoosePixelFormat(hdc, &pfd);
    if (!SetPixelFormat(hdc, indexPF, &pfd))
    {
        ...report error and terminate...
    }
}
Logger::Inst() << " ~SetPFD;" << endl;
//TEMP CONTEXT TO ACQUIRE POINTER
HGLRC tempContext = wglCreateContext(hdc);
if (!tempContext) {
    ...report error and terminate...
}
if (!wglMakeCurrent(hdc, tempContext)) {
    ...report error and terminate...
}
int major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor);
if (major < 4 || minor < 1) {
    ...report error and terminate...
}
const int attribs[] =
{
    WGL_CONTEXT_MAJOR_VERSION_ARB, major,
    WGL_CONTEXT_MINOR_VERSION_ARB, minor,
    WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
    0, 0
};
PFNWGLCREATEBUFFERREGIONARBPROC wglCreateContextAttribsARB = (PFNWGLCREATEBUFFERREGIONARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
if (!wglCreateContextAttribsARB) {
    ...report error and terminate...
}
**!!! CRASH HERE !!!**
if (!(hglrc = (HGLRC)wglCreateContextAttribsARB(hdc, 0, (UINT)attribs))) {
    ...report error and terminate...
}

调试器显示它正好发生在wglCreateContextAttribsARB(nvoglv64.dll!0000000074ccbdfa)。这对我来说是个谜。我唯一的线索是,在切换到x64后,它需要以"UINT"而不是"const-int*"形式传递的属性,我不明白这一部分,甚至不确定彼此之间的转换应该如何工作,这似乎很可疑。想法?

您有一个打字错误:wglCreateContextAttribsARB的类型错误。它应该是PFNWGLCREATECONTEXTATTRIBSARBPROC

当您以32位为目标时,它之所以有效,是因为两者的签名在32位中基本相同:

wgl创建上下文属性ARB:

typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);

wglCreateBufferRegionARB:

typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);

wglCreateContextAttribsARB的第二和第三参数是指针(HGLRC是句柄,它只是指针),而wglCreateBufferRegionARB的第二个和第三个参数是整数。在32位中,指针的大小是32位的,因此签名本质上是相同的。

在64位中,指针的大小是64位的,但整数仍然是32位的(假设您使用的是MSVC),所以您传入的两个指针被截断了。