wglMakeCurrent()是否会泄漏工作线程中的内存?

时间:2013-01-07 12:24:11

标签: windows opengl

我一直在MS Windows下用OpenGL编写服务器端的屏幕外渲染。工作流程包括以下步骤:

  1. 客户端发送卷渲染请求。

  2. 服务器收到请求,请求工作线程使用请求中包含的参数进行一些光线投射。

  3. 服务器检索渲染的图像,将其发送到客户端并终止工作线程。

  4. 一开始工作正常。但是,在10,000个请求之后,wglMakeCurrent()将失败并且可以检测到显着的内存泄漏。所以我制作了一个简化的测试程序,它只包含OpenGL上下文创建和删除。它如下所示。大约10,000次循环后,wglMakeCurrent()总是失败。有人可以告诉我代码是否有问题?我使用的是Nvidia Quadro GPU,驱动程序版本是307.45,操作系统是Windows 7 64位。

     #include <cstdio>
     #include <windows.h>
     #include <tchar.h>
     #include <process.h>
    
     LRESULT CALLBACK WndProc_GL(HWND handle, UINT message, WPARAM w_param, LPARAM l_param)
     {
       return DefWindowProc(handle, message, w_param, l_param);
     }//-------------------------------------------------------
    
     unsigned int __stdcall OpenglThreadProc(void *ptr_input)
     {
       HINSTANCE inst_handle = GetModuleHandle(NULL);
       WNDCLASS wnd_class = {CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
        (WNDPROC)WndProc_GL,
        0, 0, inst_handle, NULL, NULL, NULL, NULL,
        _T("OpenGL Hidden Window Class")
       };
       if (!RegisterClass(&wnd_class)) return 0;
       HWND window_handle = CreateWindow(_T("OpenGL Hidden Window Class"),
         _T("Window For OpenGL"),
         WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDRE N, 0, 0, 256, 256,
         NULL, NULL, inst_handle, NULL);
       if (!window_handle) return 0;
       HDC dc_handle = GetDC(window_handle);
       PIXELFORMATDESCRIPTOR ogl_pfd = {sizeof(PIXELFORMATDESCRIPTOR), 1,
         PFD_SUPPORT_OPENGL,
         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, 0, 0
       };
       int pixel_format = ChoosePixelFormat(dc_handle, &ogl_pfd);
       if (!SetPixelFormat(dc_handle, pixel_format, &ogl_pfd)) return 0;
       HGLRC rc_handle = wglCreateContext(dc_handle);
       if (!rc_handle || !wglMakeCurrent(dc_handle, rc_handle)) return 0;
    
       _tprintf_s(_T("Executing Thread %d.\n"), *(reinterpret_cast<int*>(ptr_input)) + 1);
    
       // Deletes OpenGL context and destroys window.
       wglMakeCurrent(NULL, NULL);
       wglDeleteContext(rc_handle);
       ReleaseDC(window_handle, dc_handle);
       DestroyWindow(window_handle);
       UnregisterClass(_T("OpenGL Hidden Window Class"), GetModuleHandle(NULL));
       return 1;
     }//--------
    
     int main (const int argc, TCHAR *argv[])
     {
       int i = 0; 
       for (; i < 20000; i++) {
         HANDLE running_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
           OpenglThreadProc, &i, 0, NULL));
         WaitForSingleObject(running_thread, INFINITE);
         CloseHandle(running_thread);
       }
       return 1;
    }//---------
    

    我发现这个测试程序令人困惑。 wglMakeCurrent()每次调用时都会创建一个Windows用户对象,但是这个对象不会在wglDeleteContext()中发布。即使在工作程序终止后它仍然存在,导致内存泄漏。 Windows下的用户对象存在每进程限制,因此程序最终会失败。

    当上下文创建/删除代码移动到主线程时,wglMakeCurrent()在第一次调用后不会创建新的用户对象。所以似乎wglMakeCurrent()只在新线程中创建新的用户对象。但是,由于OpenGL上下文被显式删除并且线程终止,因此也应该释放与该上下文相关联的资源。我不确定这是我的代码或驱动程序的错误。有人可以帮我吗?

0 个答案:

没有答案