Does wglMakeCurrent() leaks memory?

Hi, all:
I’ve been programming server-side offscreen rendering with OpenGL under MS Windows. The workflow consists of the following steps:

  1. A client sends a request for volume rendering.
  2. Server receives the request, forks a worker thread to do some ray-casting with parameters contained in the request.
  3. Server retrieves the rendered image, sends it to the client and terminates the worker thread.

It works fine at first. However, after 10,000 requests, wglMakeCurrent() will fail and significant memory leak can be detected. So I make a simplified test program which contains only OpenGL context creation and deletion. It’s shown below. wglMakeCurrent() always fails after about 10,000 loops. Can somebody tell me if there’s anything wrong with the code? I’m using Nvidia Quadro GPU, the driver version is 307.45, OS is Windows 7 64-bit.

#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,

INDENTWndProc_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_CLIPCHILDREN, 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.
"), (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;[/INDENT]
}//------------

int main (const int argc, TCHAR *argv)
{
int i = 0;
for (; i < 20000; i++) {

[INDENT] HANDLE running_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0,
[INDENT]OpenglThreadProc, &i, 0, NULL));
WaitForSingleObject(running_thread, INFINITE);
CloseHandle(running_thread);[/INDENT]
}
return 1;[/INDENT]
}//---------------------

I found something confusing with this test program. wglMakeCurrent() creates a Windows user object every time it’s called, but this object is not released in wglDeleteContext(). It still exists even after the worker is terminated, causing a memory leak. There is a per-process limit of user objects under Windows, so the program will eventually fail.

When the code of context creation/deletion is moved to the main thread, wglMakeCurrent() doesn’t create new user object after the first invocation. So it seems that wglMakeCurrent() only create new user object in new threads. But since the OpenGL context is explicitly deleted and the thread is terminated, resources associated with that context should be released as well. I’m not sure it’s the fault with my code or the driver. Can somebody help me with this? Thanks.

  1. You don’t need to register new window classes in every thread (unless they are different).
  2. Your graphic card won’t change during runtime, so you don’t need to choose a pixel format for every DC. Just choose for the first one and save the value for later.
  3. The problem is in the OpenGL implementation for sure. Each thread initializes one object when ogl is used(!), and, so it seems, not released when the thread is destroyed. Try using a thread pool. This way you lose the overhead for thread creation. And maybe you can re-use the already initialized render contexts and windows.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.