I have a problem with system resources seemingly not being returned on Windows 7. I have written a short test program in C that does nothing except create a bunch of windows then destroys them in an infinite loop. After each iteration of the loop the Handles count in the task manager window goes up and never returns to the starting value. Also, the memory used creeps up. After running the program long enough it crashes. Ultimately I need to be able to create and destroy OpenGL contexts. If I include the OpenGL in this simple test app the behavior is the same except that it uses up resources faster. Am I missing something?
// ResourceTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "../GL/gl.h"
#include "../GL/glext.h"
#include "../GL/wglew.h"
typedef struct _WindowInfo {
int x, y;
int width, height;
GLboolean visible;
char *title;
HWND hWnd;
HDC device_context;
GLint id;
GLint pixelFormat;
HGLRC hglrc;
} WindowInfo;
typedef GLboolean (APIENTRY *ChoosePixelFormatARBFunc_t)(HDC, GLint *, GLfloat *, GLuint, GLint *, GLuint *);
ChoosePixelFormatARBFunc_t ChoosePixelFormatARB_func;
#define WINDOW_NAME window->title
HANDLE windowDestroyed;
LONG WINAPI MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
/* int w,h; */
switch ( uMsg )
{
case WM_CREATE:
{
HDC hDC;
int attribList[100];
float fattribList[] = { 0.0, 0.0 };
int i = 0;
WindowInfo *window =
(WindowInfo *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
PIXELFORMATDESCRIPTOR *ppfd = NULL;
hDC = GetDC(hWnd);
if (window->pixelFormat <= 0)
{
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */
1, /* version number */
PFD_DRAW_TO_WINDOW | /* support window */
PFD_DOUBLEBUFFER |
PFD_SUPPORT_OPENGL, /* support OpenGL */
PFD_TYPE_RGBA, /* RGBA type */
32, /* 24-bit color depth */
0, 0, 0, 0, 0, 0, /* color bits ignored */
0, /* no alpha buffer */
0, /* shift bit ignored */
1,
0, 0, 0, 0, /* accum bits ignored */
24, /* set depth buffer */
8, /* set stencil buffer */
0, /* no auxiliary buffer */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0 /* layer masks ignored */
};
attribList[i++] = WGL_DRAW_TO_WINDOW_EXT;
attribList[i++] = GL_TRUE;
attribList[i++] = WGL_ACCELERATION_EXT;
attribList[i++] = WGL_FULL_ACCELERATION_EXT;
attribList[i++] = WGL_COLOR_BITS_EXT;
attribList[i++] = 24;
attribList[i++] = WGL_RED_BITS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_GREEN_BITS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_BLUE_BITS_EXT;
attribList[i++] = 1;
attribList[i++] = WGL_DOUBLE_BUFFER_EXT;
attribList[i++] = GL_TRUE;
attribList[i++] = WGL_DEPTH_BITS_EXT;
attribList[i++] = 1;
/* End the list */
attribList[i++] = 0;
attribList[i++] = 0;
ppfd = &pfd;
if (ChoosePixelFormatARB_func)
{
GLuint numFormats;
ChoosePixelFormatARB_func(hDC, attribList, fattribList,
1, &window->pixelFormat, &numFormats);
}
else
{
/* Okay, we were loaded manually. Call the GDI functions. */
window->pixelFormat = ChoosePixelFormat(hDC, ppfd);
}
}
else
{
PIXELFORMATDESCRIPTOR p;
ppfd = &p;
DescribePixelFormat(hDC, window->pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), ppfd);
}
if (window->pixelFormat)
{
SetPixelFormat(hDC, window->pixelFormat, ppfd);
}
}
break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
DWORD WINAPI createWindow(LPVOID args)
{
WindowInfo *window = (WindowInfo *)args;
HINSTANCE hinstance;
WNDCLASS wc;
DWORD window_style;
MSG msg;
char name[32];
HANDLE windowCreated;
static int id;
sprintf(name, "createwindow%d", window->id);
windowCreated = OpenEvent(EVENT_ALL_ACCESS, FALSE, name);
windowDestroyed = CreateEvent(NULL, TRUE, FALSE, NULL);
hinstance = GetModuleHandle( NULL );
if (!hinstance)
{
printf( "Couldn't get the module handle.\n" );
return GL_FALSE;
}
if (!GetClassInfo(hinstance, "Test_Window", &wc))
{
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC) MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "Test_Window";
if (!RegisterClass(&wc))
{
printf( "Couldn't register window class.\n" );
}
}
window_style = WS_POPUP;
window->hWnd = CreateWindowA( "Test_Window", WINDOW_NAME, window_style,
window->x, window->y, window->width, window->height, NULL, NULL, hinstance,
window);
if ( !window->hWnd )
{
printf( "Create Window failed!.\n" );
}
window->device_context = GetDC(window->hWnd);
if (window->visible)
{
ShowWindow(window->hWnd, SW_SHOWNORMAL);
}
SetEvent(windowCreated);
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.hwnd == window->hWnd)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
CloseHandle(windowCreated);
window->hWnd = NULL;
window->device_context = 0;
SetEvent(windowDestroyed);
return 0;
}
GLboolean createTestWindow(WindowInfo *window )
{
HANDLE windowCreated;
char name[32];
sprintf(name, "createwindow%d", window->id);
printf("Create window %d\n", window->id);
windowCreated = CreateEvent(NULL, TRUE, FALSE, name);
CreateThread(NULL, 2000, createWindow, (LPVOID)window, 0, NULL);
WaitForSingleObject(windowCreated, 50000);
CloseHandle(windowCreated);
printf("Window created\n");
return GL_TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
HWND hWnd;
WindowInfo window[34];
char windowTitle[34];
int i;
static int id = 1;
// Create a window
window[0].id = 1;
window[0].x = 40;
window[0].y = 600;
window[0].width = 800;
window[0].height = 600;
window[0].visible = 0; // wait to make window visible
window[0].pixelFormat = 9;
window[0].title = _strdup("Window 0");
createTestWindow(&window[0] );
// Create a context
// window[0].hglrc = wglCreateContext((HDC)window[0].device_context );
// wglMakeCurrent(window[0].device_context, window[0].hglrc);
// Load function pointers
// ChoosePixelFormatARB_func =
// (ChoosePixelFormatARBFunc_t)wglGetProcAddress("wglChoosePixelFormatARB");
// Destroy context
// wglMakeCurrent(window[0].device_context, 0);
// wglDeleteContext(window[0].hglrc);
// DeleteDC(window[0].device_context);
// Destroy window
PostMessage(window[0].hWnd, WM_QUIT, 0, 0);
free(window[0].title);
while (1)
{
for (i = 0; i < 34; i++)
{
// Create 34 windows
window[i].id = i + 1;
window[i].x = 40;
window[i].y = 600;
window[i].width = 800;
window[i].height = 600;
window[i].visible = 1; // wait to make window visible
window[i].pixelFormat = 9;
sprintf(windowTitle, "Window %d", window[i].id);
window[i].title = _strdup(windowTitle);
createTestWindow(&window[i] );
// Create 34 contexts
// window[i].hglrc = wglCreateContext((HDC)window[i].device_context );
// wglMakeCurrent(window[i].device_context, window[i].hglrc);
}
Sleep(3000);
for (i = 0; i < 34; i++)
{
// Destroy contexts
// wglMakeCurrent(window[i].device_context, 0);
// wglDeleteContext(window[i].hglrc);
// DeleteDC(window[i].device_context);
// Destroy windows
PostMessage(window[i].hWnd, WM_QUIT, 0, 0);
Sleep(100);
printf("%s destroyed\n", window[i].title);
free(window[i].title);
}
Sleep(2000);
}
return 0;
}