-
July 14th, 2009, 09:44 PM
#1
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;
}
-
July 15th, 2009, 08:47 AM
#2
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.
-
July 20th, 2009, 06:16 AM
#3
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|