VC debugging
No wonder many predecessors say that debugging is the most basic skill of a programmer, and its importance is even greater than learning a language. A programmer who does not debug means that, even if he can speak a language, he cannot compile any good software.
Most of the programs I used to come into contact with have some ideas and methods. The debugging problems are relatively small. Recently, I have been exploring for debugging and have come into contact with many new debugging methods, I also checked the summary of many predecessors and benefited a lot. I summarized the previous and new GAINS as follows:
VC debugging
Set
To debug a program, you must first include debugging information in the program. Generally, the Debug Configuration in a project created from AppWizard automatically contains debugging information, the program designer can add debugging information in any Configuration, including the Release version.
To add debugging information, follow these steps:
- Open the Project settings dialog box (you can use the shortcut key ALT + F7 or IDE menu Project/Settings)
- Select the C/C ++ page, and select general in Category. A Debug Info drop-down list box is displayed. The debugging information options include:
Command Line |
Project settings |
Description |
None |
None |
No debugging information |
/ZD |
Line numbers only |
The target file or executable file only contains the global and exported symbols and code line information, excluding the symbol debugging information. |
/Z7 |
C 7.0-compatible |
The target file or executable file contains the line number and all symbol debugging information, including the variable name and type, function and prototype. |
/Zi |
Program database |
Create a library (PDB), including type information and symbol debugging information. |
/Zi |
Program database for edit and continue |
In addition to the previous/Zi functions, this option allows you to modify and continue the code during debugging. This option also invalidates the optimization function set by # pragma. |
- Select the Link page and select the check box "Generate Debug Info". This option will allow the connector to write debugging information into the executable file and DLL
- If the options above Program Database are set on the C/C ++ page, Link incrementally can be selected. By selecting this option, the program can be compiled (that is, incremental compilation) on the basis of the previous compilation, rather than starting from the beginning each time.
Debugging method:
1. Use Assert (Principle: Make it as simple as possible). assert takes effect only under debug and will not be compiled under release.
2. Defensive Programming
3. Use Trace
4. Use GetLastError to check the returned value and get the error code to analyze the cause of the error.
5. Record the error information to the file.
Location breakpoint (Location Breakpoint)
The most common breakpoint is a normal position breakpoint. A position breakpoint is set in a line of the source program by pressing F9. However, for many problems, this simple breakpoint has limited function. For example, the following code:
Void CForDebugDlg: OnOK ()
{
For (int I = 0; I <1000; I ++) //
{
Int k = I * 10-2; // B
SendTo (k); // C
Int tmp = DoSome (I); // D
Int j = I/tmp; // E
}
}
When this function is executed, the program crashes in line E and finds that tmp is 0 at this time. Assuming that tmp should not be 0, why is it 0 at this time? So it is best to track how the DoSome function runs in this loop, but because it is in the loop body, if you set a breakpoint in line E, you may need to press F5 (GO) many times. In this way, it is very painful to keep pressing. You can easily solve this problem by using the VC6 breakpoint Modification Conditions. The procedure is as follows.
1 Ctrl + B Open the breakpoint setting box, such:
Figure 1Set advanced position breakpoint
2. Select the breakpoint where Row D is located, and then click the condition button. In the bottom edit box of the pop-up dialog box, enter a large number, depending on the application. Here 1000 is enough.
3. Press F5 to run the program again, and the program is interrupted. Ctrl + B Open the breakpoint box and find the breakpoint followed by a series of instructions:... 487 times remaining. It means that the remaining 487 times are not executed, that is to say, an error occurs when the execution reaches 513 (1000-487. Therefore, as described in step 2, change the number of skips for this breakpoint to 1000.
4. Run the program again. The program executes 513 cycles and stops at the breakpoint automatically. In this case, we can carefully check how DoSome returns 0. In this way, you can avoid finger pain and save time.
Let's look at other Modification Conditions of the location breakpoint. For exampleFigure 1As shown in, under "Enter the expression to be evaluated:", you can Enter some conditions. When these conditions are met, the breakpoint starts. For example, if we need to stop the program when I is 100, we can enter "I =" in the editing box. 100" .
In addition, if you enter only the variable name in the edit box, the breakpoint starts only when the variable changes. This is convenient for detecting when a variable is modified, especially for some large programs.
Using the Modification Conditions of the location breakpoint can greatly solve some problems.
Data breakpoint (Data Breakpoint)
During software debugging, some data may be inexplicably modified (for example, some arrays may overwrite other variables ), finding out where the code causes this memory to be changed is tricky (without the help of the debugger ). The proper use of data breakpoints can help you quickly locate when and where the data is modified. For example, the following program:
# Include "stdafx. h"
# Include
Int main (int argc, char * argv [])
{
Char szName1 [10];
Char szName2 [4];
Strcpy (szName1, "shenzhen ");
Printf ("% s \ n", szName1); //
Strcpy (szName2, "vckbase"); // B
Printf ("% s \ n", szName1 );
Printf ("% s \ n", szName2 );
Return 0;
}
The output of this program is
SzName1: shenzhen
SzName1: ase
SzName2: vckbase
When Will szName1 be modified? Because szName1 code is not significantly modified. We can first set A normal breakpoint in line A, F5 runs the program, and the program stops in line. Then we set another data breakpoint. For example:
Figure 2Data breakpoint
F5 continues to run. The program stops at line B, indicating that szName1 has been modified in the code at line B. Why didn't I modify szName1 at location B? However, the debugger specifies this line. Generally, this line won't be wrong, so let's just take a look at the program. Oh, you found that szName2 has only 4 bytes, and strcpy has 7 bytes, therefore, szName1 is overwritten.
A Data breakpoint is not only valid for variable changes, but also can be used to set whether the variable is equal to a certain value. For example, you can change the Red Circle in Figure 2 to the condition "szName2 [0] = '''y' '''", when the first character of szName2 is y, the breakpoint starts.
It can be seen that a big difference between the data breakpoint and the position breakpoint is that you do not need to specify which line of code to set the breakpoint.
Other debugging methods: the system provides a series of special functions or macros to process information related to the Debug version, as follows:
Macro name/function name |
Description |
Trace |
The usage is exactly the same as that of printf. It outputs debugging information in the output box. |
Assert |
It receives an expression. If the expression is true, there is no action. Otherwise, the current program is interrupted. For the interruption caused by this macro in the system, you should consider that your function call does not meet the prerequisites for the system to call this function. For example, setwindowtext is called for a window that has not yet been created. |
Verify |
Similar to the assert function, the difference is that in the release version, assert does not calculate the value of the input expression, but verify calculates the value of the expression. |
Value
Watch
VC supports viewing the values of variables, expressions, and memory. All these observations must be performed when the breakpoint is interrupted.
The viewing variable value is the simplest. When the breakpoint arrives, move the cursor over the variable and you will be able to see the value of the variable after a while.
VC provides a Watch mechanism to Watch the values of variables and expressions. In the breakpoint status, right-click the variable and select Quick Watch. A dialog box is displayed, showing the value of the variable.
Click the Watch button on the Debug toolbar to display a Watch view (wattings, Watch2, Watch3, and watmethane). Enter a variable or expression in the view, you can observe the values of variables or expressions. Note: This expression does not have any side effects. For example, the ++ operator is definitely forbidden to be used in this expression, because this operator will modify the value of the variable, resulting in the destruction of the software logic.
Memory
Because the pointer points to an array, Watch can only display the value of the first element. You can use the memory function to display the subsequent content of an array or a piece of memory. Click the memory button on the Debug toolbar. A dialog box is displayed. Enter the address to display the memory content pointed to by the address.
Varibles
The Varibles button on the Debug toolbar displays the values of all variables visible in the current execution context. In particular, the variables involved in the current command are displayed in red.
Register
The Reigsters button on the Debug toolbar pops up to display the values of all current registers.
Debugging skills:
1. debug and run F5 in VC ++
A) you can see the information printed with TRACE in the output Debug window.
B) The Call Stack of the program can be seen in the Call Stack window.
2. When the Debug version is running, a crash occurs. Select retry for debugging. Analyze the error location and cause by checking the Call Stack.
3. Use the ing file for debugging
A) create a ing file: link entry in Project settings, select Generate mapfile, and output the program code address:/MAPINFO: LINES. The output sequence number is/MAPINFO: EXPORTS.
B) when the program is released, the ing files of all modules should be archived.
C) view the ing file: see the file "identify error lines of source code through the crash address.
4. Release versions that can be debugged
In Project Settings, select debug info for item C ++ as program database, and debug info and Microsoft format for item link.
5. view the API error code. In the Watch window, enter @ err to view the error code or @ err, HR. ", HR" indicates the description of the error code.
6. set next statement: this function can be directly redirected to the specified code line for execution. It is generally used to test the code for exception handling.
7. debug memory variable changes: Stop when Memory changes .???
Process Control
VC allows the interrupted program to continue running, run in a single step, and run at the specified cursor, corresponding to the shortcut keys F5, F10/F11, and CTRL + F10 respectively. Each shortcut key has the following functions:
Shortcut Key |
Description |
F5 |
Debug/continue running |
F10 |
In a single step, if a sub-function is involved, the sub-function is not entered. |
F11 |
In a single step, if a sub-function is involved, enter the sub-function. |
CTRL + F10 |
Run to the current cursor. |
F7 |
Reconstruction |
F9 |
Set breakpoint/clear breakpoint |
CTRL + Shift + F9 |
Clear all breakpoints |
Shift + F5 |
End debugging |
Call Stack
The call stack reflects the sequence in which the current breakpoint function is called. Click call stack on the debug toolbar to display the call stack dialog box. The callstack dialog box displays a call series. The top part is the current function, and the top part is the upper-level function that calls the function in sequence. Click these function names to jump to the corresponding function.
Follow
A good programmer should not give all the judgment to the compiler and debugger, and should implement program protection and error locating in the program. Specific measures include:
- For all functions with returned values, you should check the returned values unless you are sure that this function call will never go wrong, or you do not care if it is wrong.
- Some functions return errors. You need to use other functions to obtain the error details. For example, if accept returns invalid_socket, the accept fails. To identify the cause of the failure, you should immediately use wsagetlasterror to obtain the error code and solve the problem accordingly.
- Some functions throw an error through the exception mechanism and use the try-catch statement to check the error.
- Programmers should handle the errors they can handle at the underlying level. If they cannot handle the errors, they should report the errors to users so that they can decide how to handle them. If an exception occurs in the program, but the error information returned by the return value and other mechanisms is not judged, the difficulty of error searching is only increased.
In addition: To compile programs in VC, you should not write CPP/H files at the beginning, but create a suitable project first. Only in this way can VC select the appropriate compilation and connection options. For CPP files added to the project, check whether the stdafx. h header file is explicitly included in the first line. This is the pre-compiled header file set by Microsoft Visual Studio to speed up compilation. All code before this # include "stdafx. H" line will be ignored, so other header files should be included after this line.
Because the. c file cannot contain stdafx. H, you can use project settings to set its pre-compilation header to "not used":
- The Project Settings dialog box is displayed.
- Select C/C ++
- Select precompilation header for category
- Select not to use the pre-compiled header.
Easy-to-Debug code style:
No global variables
All variables must be initialized. member variables must be initialized in the constructor.
Try to use const
Detailed notes
Summary
The most important part of debugging is to think about where your program may go wrong, and then use your debugger to confirm your guess.