CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 3 of 3
  1. #1
    Join Date
    Jul 2009
    Posts
    2

    Curious win32 memory problem

    I have a very interesting problem with a basic application that I am writing. The whole project is basically the auto-generated c++ win32 application; I just added a dialog box and the appropriate handles for it. What this dialog box does is it takes user input from an edit box, loads it into a memory buffer, then adds the string to a listbox. The problem has to do with freeing up the allocated memory for text in the dialog box. I get a pretty standard warning from visual studio when I debug it:

    "Windows has triggered a breakpoint in Test.exe. This may be due to a corruption of the heap, and indicates a bug in Test.exe or any of the DLLs it has loaded."

    Here is the interesting part of my problem: When the user inputs say "asdf", the whole thing works without issue. But when certain strings are input such as "adf", thats when I get the error. So in short, the code works half the time and seemingly at random. If anyone can give me a hand, that would be much appreciated. There is a lot of code, and if you have any questions about what I am doing at any point in the code, or if you need to see my other includes (.rc, .h, etc.) let me know.

    Code:
    #include "stdafx.h"
    #include "Test.h"
    
    #define MAX_LOADSTRING 100
    
    // Global Variables:
    HINSTANCE hInst;								// current instance
    TCHAR szTitle[MAX_LOADSTRING];					// The title bar text
    TCHAR szWindowClass[MAX_LOADSTRING];			// the main window class name
    
    // Forward declarations of functions included in this code module:
    ATOM				MyRegisterClass(HINSTANCE hInstance);
    BOOL				InitInstance(HINSTANCE, int);
    LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK	ControlDlg(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY _tWinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPTSTR    lpCmdLine,
                         int       nCmdShow)
    {
    	UNREFERENCED_PARAMETER(hPrevInstance);
    	UNREFERENCED_PARAMETER(lpCmdLine);
    
     	// TODO: Place code here.
    	MSG msg;
    	HACCEL hAccelTable;
    
    	// Initialize global strings
    	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    	LoadString(hInstance, IDC_TEST, szWindowClass, MAX_LOADSTRING);
    	MyRegisterClass(hInstance);
    
    	// Perform application initialization:
    	if (!InitInstance (hInstance, nCmdShow))
    	{
    		return FALSE;
    	}
    
    	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST));
    
    	// Main message loop:
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}
    
    	return (int) msg.wParam;
    }
    
    
    
    //
    //  FUNCTION: MyRegisterClass()
    //
    //  PURPOSE: Registers the window class.
    //
    //  COMMENTS:
    //
    //    This function and its usage are only necessary if you want this code
    //    to be compatible with Win32 systems prior to the 'RegisterClassEx'
    //    function that was added to Windows 95. It is important to call this function
    //    so that the application will get 'well formed' small icons associated
    //    with it.
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
    	WNDCLASSEX wcex;
    
    	wcex.cbSize = sizeof(WNDCLASSEX);
    
    	wcex.style			= CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc	= WndProc;
    	wcex.cbClsExtra		= 0;
    	wcex.cbWndExtra		= 0;
    	wcex.hInstance		= hInstance;
    	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST));
    	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
    	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
    	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_TEST);
    	wcex.lpszClassName	= szWindowClass;
    	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
    	return RegisterClassEx(&wcex);
    }
    
    //
    //   FUNCTION: InitInstance(HINSTANCE, int)
    //
    //   PURPOSE: Saves instance handle and creates main window
    //
    //   COMMENTS:
    //
    //        In this function, we save the instance handle in a global variable and
    //        create and display the main program window.
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       HWND hWnd;
    
       hInst = hInstance; // Store instance handle in our global variable
    
       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    
       if (!hWnd)
       {
    	   MessageBox(hWnd, L"Error creating window", L"Error", MB_ICONSTOP | MB_OK);
    	   return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    
    //
    //  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  PURPOSE:  Processes messages for the main window.
    //
    //  WM_COMMAND	- process the application menu
    //  WM_PAINT	- Paint the main window
    //  WM_DESTROY	- post a quit message and return
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	int wmId, wmEvent;
    	PAINTSTRUCT ps;
    	HDC hdc;
    
    	switch (message)
    	{
    	case WM_COMMAND:
    		wmId    = LOWORD(wParam);
    		wmEvent = HIWORD(wParam);
    		// Parse the menu selections:
    		switch (wmId)
    		{
    		case IDM_ABOUT:
    			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    			break;
    		case IDM_CONTROL:
    			DialogBox(hInst, MAKEINTRESOURCE(IDD_CONTROL), hWnd, ControlDlg);
    			break;
    		case IDM_EXIT:
    			DestroyWindow(hWnd);
    			break;
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);
    		}
    		break;
    	case WM_PAINT:
    		hdc = BeginPaint(hWnd, &ps);
    		// TODO: Add any drawing code here...
    		EndPaint(hWnd, &ps);
    		break;
    	case WM_LBUTTONDOWN:
    		{
    			WCHAR szFileName[MAX_PATH];
    			HINSTANCE inst;
    			
    			inst = GetModuleHandle(NULL);
    			GetModuleFileName(inst, szFileName,	MAX_PATH);
    			MessageBox(hWnd, szFileName, L"The name of this project is:", MB_ICONINFORMATION | MB_OK);
    		}
    		break;
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProc(hWnd, message, wParam, lParam);
    	}
    	return 0;
    }
    
    // Message handler for about box.
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	UNREFERENCED_PARAMETER(lParam);
    	switch (message)
    	{
    	case WM_INITDIALOG:
    		return (INT_PTR)TRUE;
    
    	case WM_COMMAND:
    		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
    		{
    			EndDialog(hDlg, LOWORD(wParam));
    			return (INT_PTR)TRUE;
    		}
    		break;
    	}
    	return (INT_PTR)FALSE;
    }
    // Message handler for the Control Dialog.
    INT_PTR CALLBACK ControlDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	UNREFERENCED_PARAMETER(lParam);
    	switch (message)
    	{
    		case WM_INITDIALOG:
    			return (INT_PTR)TRUE;
    
    		case WM_COMMAND:
    		{
    			int dlgId = LOWORD(wParam);
    
    			switch (dlgId)
    			{
    				case IDOK:
    				{	
    					int length = GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT));
    
    					if (length > 0)
    					{
    						HGLOBAL hDlgBuf = GlobalAlloc(GHND, length + 1);
    						LPWSTR buffer = (LPWSTR) hDlgBuf;
    
    						GetDlgItemText(hDlg, IDC_EDIT, buffer, length + 1);
    						SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)buffer);
    / **********************/	GlobalFree(hDlgBuf);  // This is where windows errors
    						return (INT_PTR)TRUE;
    					}
    					else
    					{
    						MessageBox(hDlg, L"You didnt enter anything!", L"", MB_ICONINFORMATION | MB_OK);
    						return (INT_PTR)TRUE;
    					}
    				}
    					break;  // case IDOK
    				case IDC_CLEAR:
    					SendDlgItemMessage(hDlg, IDC_LIST, LB_RESETCONTENT, 0, 0);
    					return (INT_PTR)TRUE;
    					break;
    				case IDCANCEL:
    					EndDialog(hDlg, LOWORD(wParam));
    					return (INT_PTR)TRUE;
    					break;
    			}
    		}
    			break;
    	}
    	return (INT_PTR)FALSE;
    }

  2. #2
    Join Date
    Apr 2009
    Posts
    598

    Re: Curious win32 memory problem

    int length = GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT));
    if (length > 0)
    {
    HGLOBAL hDlgBuf = GlobalAlloc(GHND, length + 1);
    LPWSTR buffer = (LPWSTR) hDlgBuf;
    GetDlgItemText(hDlg, IDC_EDIT, buffer, length + 1);
    SendDlgItemMessage(hDlg, IDC_LIST, LB_ADDSTRING, 0, (LPARAM)buffer);
    / **********************/ GlobalFree(hDlgBuf); // This is where windows errors
    return (INT_PTR)TRUE;
    }
    SendDlgItemMessage() places a message in the queue of the Dialog windows, but there is no guarantee, the message will be read at once, before GlobalFree is executed.

    In this case, it seems the problem could be solved with a global or a static buffer instead of a buffer allocated on the fly.

  3. #3
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,620

    Re: Curious win32 memory problem

    From MSDN:
    Remarks

    The SendDlgItemMessage function does not return until the message has been processed.
    It's totally enigmatic to me why anybody to use global memory as temporary buffer. Besides, GMEM_MOVEABLE requires GlobalLock to be called on handle.
    Last edited by Igor Vartanov; July 20th, 2009 at 06:27 AM.
    Best regards,
    Igor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured