|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
|
|
Be the architects of evolution and help create the mobile internet future. It’s your move---enter to win here! |
|
#1
|
|||
|
|||
|
Win32 - Complex access violation issue..
This might be a bit of a puzzle, so I will try to explain it as best I can. I am programming a simple client using the win32 API, and it makes use of the MDI. The manner in which I spawn MDI windows is with the use of CreateWindowEx, specifying the WS_EX_MDICHILD flag, with a window class specified that i have properly registered for it. To keep track of window data, I use SetProp and GetProp to get and set a window property for that particular set of data, which is a pointer to a struct that contains all the information the window will need. My issue appears when handling the WM_CLOSE message in the MDI child's window procedure. Allow me to show you the key points in the code that affect the way this message is handled:
Code:
...
case WM_CLOSE:
if(OnClose(hwnd, message, wParam, lParam)) {
RemoveProp(hwnd, "WindowData");
return DefMDIChildProc(hwnd, message, wParam, lParam);
} else {
return 0;
}
...
The OnClose procedure is defined like so: Code:
BOOL OnClose(HWND h, UINT m, WPARAM w, LPARAM l) {
lpChildWindow cw = (lpChildWindow)GetProp(h, "WindowData");
int SelectedTabIndex = SendMessage(h, TCM_GETCURSEL, 0, 0);
if(SelectedTabIndex > 0) {
lpdchitem tmp = GetDialogFromTabIndex(SelectedTabIndex, cw);
lpTabDlg dlgtmp = (lpTabDlg)tmp->Data;
if(dlgtmp) {
DestroyWindow(dlgtmp->Dialog);
EnterCriticalSection(&cw->Sync);
RemoveItemFromList(tmp, cw->FirstPM, cw->LastPM);
LeaveCriticalSection(&cw->Sync);
return 0;
}
} else {
if(MessageBox(h, "Are you sure you want to close this window?",
"Friendly Confirmation", MB_YESNO) == IDYES) {
EnterCriticalSection(&cw->Sync);
ClearTheList(cw->FirstPM, cw->LastPM);
LeaveCriticalSection(&cw->Sync);
return 1;
}
}
return 0;
}
For further information about the procedures carried out within this one, I will show the function ClearTheList and RemoveItemFromList, which are functions to manage a double-linked list of pointers: Code:
BOOL RemoveItemFromList(lpdchitem Item, lpdchitem FirstItem, lpdchitem LastItem) {
if(Item == FirstItem) {
FirstItem = FirstItem->Next;
FirstItem->Prev = NULL;
} else if(Item = LastItem) {
LastItem = LastItem->Prev;
LastItem->Next = NULL;
} else {
lpdchitem prv = Item->Prev;
lpdchitem nxt = Item->Next;
prv->Next = nxt;
nxt->Prev = prv;
}
GlobalFree(Item->Data);
GlobalFree(Item);
return true;
}
BOOL ClearTheList(lpdchitem FirstItem, lpdchitem LastItem) {
if(FirstItem != NULL) {
lpdchitem temp = FirstItem;
lpdchitem fwd;
while(temp != NULL) {
if(temp->Next) {
fwd = temp->Next;
} else {
fwd = NULL;
}
GlobalFree(temp->Data);
GlobalFree(temp);
temp = fwd;
}
}
return true;
}
Of course, you might be curious of what I store in the type lpChildWindow: Code:
typedef struct _TabDlg {
struct _TabDlg *Next;
struct _TabDlg *Prev;
HWND Dialog;
int TabIndex;
} *lpTabDlg;
typedef struct _ChildWindow {
HWND hwndWindow;
LVITEM *lvWindowItem;
HWND Hub;
CRITICAL_SECTION Sync;
lpdchitem FirstPM;
lpdchitem LastPM;
char *lpszWindowText;
char *lpszAddressText;
char *lpszUserCountText;
void *Data;
} *lpChildWindow;
The Access Violation error appears surprisingly in the middle of the main window's message loop during a call to TranslateMessage, and it shows an access violation reading from location 0x00000014, which is rather puzzling. If I comment the following lines from the above OnClose procedure, there is no access violation: Code:
EnterCriticalSection(&cw->Sync); ClearTheList(cw->FirstPM, cw->LastPM); LeaveCriticalSection(&cw->Sync); However, I feel this is very needed, since doing that will clear the data in the linked list of the "cw" structure. The FirstPM and LastPM are allocated to keep track of the tabs that are spawned in runtime. I have not finished the project yet, since I have this issue, so the tabs do not spawn as of yet. If you are also wondering, I do initialize the critical section of the lpChildWindow structure after CreateWindowEx is called. If you need more of the code, let me know. I think this is enough information for someone to spot out why the access violation error pops up. In addition, as I forgot to mention... If I comment out the call to MessageBox in OnClose, as well as the brackets belonging to the conditional statement, the debugger breaks on the following line: Code:
int SelectedTabIndex = SendMessage(h, TCM_GETCURSEL, 0, 0); This time, an access violation exception reading from location 0x0000008 appears, which is even more strange to me. The level of frustration just keeps building up the more I try to solve this problem. Perhaps one of you is more familiar with this kind of dilemma. |
|
#2
|
||||
|
||||
|
Step through there with a debugger or printf out some values. You've got a bunged pointer.
__________________
C/C++ pointers (Original in the "Commonly Asked Questions" thread). |
|
#3
|
|||
|
|||
|
Quote:
When i broke at the line with: Code:
int SelectedTabIndex = SendMessage(h, TCM_GETCURSEL, 0, 0); I noticed that the value of "h" suddenly becomes 0x00000000 when i step into the next line. This is rather weird because SendMessage should not do anything, to my knowledge, that writes the value of the Handle i am sending to... (EDIT) And when i step into the line after: Code:
if(MessageBox(h, "Are you sure you want to close this window?",
"Friendly Confirmation", MB_YESNO) == IDYES) {
I end up with "h" being edited somehow to a value of 0x00000006, which gets even more peculiar. Perhaps it is some mixup in the CPU registers? (I have a minimal knowledge of Assembly and you tend to see weird things when programming with it, but not like this :P) OK... So now i stepped into the statement and it breaks with an error after EnterCriticalSection is called, breaking on a line in the main window procedure, which puzzles me, since what I am processing is a window message from the MDI child, not the main window... Here is the main procedure, in case you are curious: Code:
LRESULT CALLBACK ClientWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_CREATE:
{
CreateMDIClient(hwnd);
DefFrameProc(hwnd, hwndMdiClient, message, wParam, lParam);
}
break;
case WM_NOTIFY:
{
switch(((LPNMHDR)lParam)->code) {
case TTN_GETDISPINFO:
{
LPTOOLTIPTEXT lpText = (LPTOOLTIPTEXT)lParam;
lpText->hinst = hInstClient;
UINT_PTR btnFrom = lpText->hdr.idFrom;
switch(btnFrom) {
case IDCTL_PUBLICHUBS:
lpText->lpszText = lpszPublicHubsToolTipText;
break;
case IDCTL_RECONNECT:
lpText->lpszText = lpszReconnectToolTipText;
break;
case IDCTL_FAVORITES:
lpText->lpszText = lpszFavoritesToolTipText;
break;
}
}
break;
case LVN_GETDISPINFO:
break;
}
}
break;
case WM_SIZE:
{
RecalculateMdiClientSize(hwnd);
}
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case ID_FILE_QUICKCONNECT:
{
hwndQuickConnect = CreateDialog(hInstClient, MAKEINTRESOURCE(IDD_QUICKCONNECT),
hwnd, (DLGPROC)QuickConnectProc);
ShowWindow(hwndQuickConnect, 1);
}
break;
default:
if(LOWORD(wParam) >= MDI_FIRST_CHILD) {
DefFrameProc(hwnd, hwndMdiClient, message, wParam, lParam);
} else {
HWND h = (HWND)SendMessage(hwndMdiClient, WM_MDIGETACTIVE, 0, 0);
if(h) {
SendMessage(h, WM_COMMAND, wParam, lParam);
}
}
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return(DefFrameProc(hwnd, hwndMdiClient, message, wParam, lParam));
}
return 0;
}
I know the code I am showing is rather lengthy, and forgive me for being very broad, but this error seems to be encompassing the entire program's integrity. |
|
#4
|
|||
|
|||
|
When you learn this MFC or Win32 API, i also want to know.
Please post some guideline for me to get started. |
![]() |
| Viewing: Dev Shed Forums > Programming Languages > C Programming > Win32 - Complex access violation issue.. |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|
|
|