Visual C++ Debugging: Step by Step Introduction
Q: I have this piece of code that crashes when I try to access dlg.control. What can be wrong?
Q: I am reading and writing in a buffer, but memcpy causes my application to crash? I have allocated enough memory. Am I missing something?
Q: My program gives "Unhandled exception in myprogram.exe. 0xC0000005: Access Violation." How to debug these kind of errors? What should I check for?
Q: I have a dialog with a control that works very fine until a mouse button is clicked on it, when it shows an assertion failure. Can anyone help me out as why this assertions failure and how to fix?
A: All right! Enough questions, I got the point. And there is a single answer for all: use the debugger. You can do that either by pressing F5 or use the menu:
- VC++ 6.0: Build, Start Debug, Go
- VC++ 7.x, 8.0: Debug, Start
I'll show you with a dummy example how can you spot the problem running in the debugger.
When your application asserts, for instance because of this code:
you get a message like this:
button.ShowWindow(SW_SHOW); // control is not created, it will assert
If your application encounters an unhandled exception, for instance for using a NULL pointer like in this example:
you get a message like this:
CButton* button = NULL;
button->ShowWindow(SW_SHOW); // no object, no control
In the first case press Retry, in the second case press OK. In either situation you are led to the problem. (For the following I'll use the first code sample.)
Unhandled exception in server.exe (MFC42D.DLL): 0xC0000005: Access Violation.
It's easy to understand from this code that the asserting occurs because 'm_hWnd' is not a valid window handle (place the mouse cursor over 'm_hWnd' to see its value). However, spotting the 'ASSERT' that failed is sometimes only the first step. In the case presented here this 'ASSERT' is inside MFC sources. You have to go to the code written by you that cause it to fail. For this you must open the 'Call Stack' window, which is available only during debugging.
On top is the last called function, on the bottom (not visible here) is the entry point for the application:
The yellow arrow shows the current view function. If you double click a function you are redirected to the body of that function where the call occurred.
WinMain(HINSTANCE__* 0x00400000, HINSTANCE__* 0x00000000, char* 0x00141f1e, int 1) line 30
WinMainCRTStartup() line 330 + 54 bytes
In this picture you can see parts of the 'CServerDlg::OnInitDialog()' method. The green pointer of the left bar indicates the calling point, but sometimes, like in this case, it points one instruction after. In my example the assert occurred in the body of 'CWnd::ShowWindow', which was called from the highlighted line. At this point it's easy to realize the problem: the button control was not created before the 'ShowWindow()' call was made, which is the reason 'm_hWnd' was not a valid handle.
Now go and debug your code...