This article mainly introduces some tips for debugging code when using VC6.0 to develop C language programs. For more information, see
(1) set a fixed or temporary breakpoint
The so-called breakpoint is to specify a line in the program, so that the program runs until the line stops running, so that programmers can observe and analyze the running process of the program. These situations generally include:
① Observe the current value of the variable in the program in the Variable Window (Varibles.The programmer observes these values to compare them with the expected values. If they are inconsistent with the expected values, the program running before the breakpoint must have a problem somewhere to narrow down the fault scope. For example, the following program calculates cos (x) and shows that the result is 0.046414 no matter how much x is input during running.
Copy codeThe Code is as follows:
# Include <stdio. h>
# Include <math. h>
Void main ()
{
Int x;
Printf ("Please input x :");
Scanf ("% d", & x );
Printf ("cos (x) = % fn", cos (x ));
}
In this program, if you do not see the problem-the problem is difficult to see when the program is long and complex, you should use debugging methods to locate the fault location.
② Observe the value of a specified variable or expression in the monitoring window (Watch.When there are many variables, it may be inconvenient to use the Varibles window. You can use the Watch window to observe the changes of key variables in a purposeful and systematic manner.
③ In the output window, check whether the current output of the program is as expected.Similarly, if they are inconsistent, the program running before the breakpoint must have a problem somewhere.
④ Observe the data changes in the Memory window (Memory.In this window, you can directly query and modify the data of any address. For beginners, it provides a more profound understanding of how various variables, arrays, and structures occupy the memory, as well as the out-of-bounds process of arrays.
⑤ Observe nested function calls in the Call Stack window.This window is helpful for fault analysis when the function call relationship is complex or recursive.
(2) One-step execution Program
Let the program be executed step by step and observe whether the execution process meets the pre-requirements. For example, the following Program expects to read two numbers (x and y) from the keyboard to determine whether x and y are equal. If they are equal, x = y is displayed on the screen, if not equal, x <> y is displayed. This is a required function, but the actual running status of the program is: no matter what you enter, x = y and x & lt;> y will be displayed on the screen, the program must be faulty, however, on the surface, the problem may not be found. If you use one-step execution, you can locate the fault point and narrow down the scope. For example, if "2, 3" is entered during a single step, the values of x and y are indeed 2 and 3, "printf (" x = yn ");" should not be executed in this case, but the single-step trace is found to be executed, so most of the problems are "if (x = y )".
Copy codeThe Code is as follows:
# Include <stdio. h>
Void main ()
{
Int x, y;
Printf ("Please input x, y :");
Scanf ("% d, % d", & x, & y );
If (x = y)
{
Printf ("x = yn ");
}
Else;
{
Printf ("x <> yn ");
}
}
In the process of one-Step execution, steps Over, Step Into, Step Out, Run to Cursor, and other methods should be flexibly applied to improve the debugging efficiency. We recommend that you remember and use shortcut keys for menu items such as "Step Over", "Step Into", "Step Out", and "Run to Cursor" during program debugging, which may be unfamiliar at the beginning and slow in operations, however, after a period of time, it will produce good results and improve efficiency.
(3) Use assertions
The statement breaking is to check certain hypothetical conditions (it can be understood that if the conditions are true, there is no action; otherwise, a report should be reported). It can quickly detect and locate software problems, at the same time, automatic alarms are triggered for system errors. Assertions can be used to locate problems that are hidden deep in the system and difficult to find by other means, thus shortening the software issue locating time and improving the testability of the system. In actual applications, You can flexibly design Assertions based on specific situations.
When using assertions, you must add the following at the beginning of the program:
# Include <assert. h>
① Use assertions to confirm the function parameters. Example: If a function parameter has a pointer, you can check it before using the pointer to prevent others from using a null pointer as a parameter when calling this function. The Code is as follows:
Copy codeThe Code is as follows:
Int exam_fun (unsigned char * str)
{
Assert (str! = NULL); // assertion "the pointer is not NULL". If it is NULL (the assertion is not true), an error is returned.
... // Other program code
}
② Assertion can be used to determine whether a fault has occurred. Example: The running result of the following program section is incorrect. It is difficult to check and I have never known where the problem is. Therefore, it is recommended to analyze what the normal running status of the program should be, and whether an exception occurs during the running process, and Use assertions for all (or critical status) should be normal, it is very likely to find the cause of the exception, and the debugging efficiency is very high. For this program segment, we assert that the value of variable I should be "I> = 0 & I <SIZE" and is critical, but is it possible to be accidentally modified during the running process (for example, if other variables are out of the range), you can use assertion to check whether such a situation has occurred.
Copy codeThe Code is as follows:
For (I = 0; I <SIZE; I ++)
{
... // Other program code
Assert (I> = 0 & I <SIZE); // assertion "I's normal value range". If the assert is not true, an error is returned.
Array [I] = I;
... // Other program code
}
When the assertions are not established (an exception occurs), the system will immediately report an error. At this time, you can enter the program debugging status and check the program running status.
(4) operation menu related to debugging: Build menu
Compile: press Ctrl + F7. Compile the source program file in the source code window to check whether there are syntax errors or warnings. If yes, it will be displayed in the Output window.
Build: shortcut key F7. Connect the relevant files in the current project. If an error occurs, it will be displayed in the Output window.
Execute: press Ctrl + F5. An executable program (File) that has been compiled and connected successfully ).
Start Debug: select this option to bring up the Sub-menu, which contains several options for starting the debugger to run. For example, the Go option is used to run the program from the current statement until a breakpoint or program end occurs. The Step Into option starts the single-Step execution program, when a function is called, enter the function and execute it from the ground up. The Run to Cursor option causes the program to pause execution when the current mouse Cursor is located. (Note: before using this option, first, you need to set the cursor to a program line you want to pause ). After selecting the menu, the debugger is started. The Debug menu (instead of the Build menu) appears in the menu bar ).
(5) Debug-related operation menus: Debug menus
The Debug menu appears only after the debugger is started (instead of the Build menu ).
Go: Enter F5. Start the program from the current statement and continue running the program until it encounters a breakpoint or stops when the program ends (the function is the same as that of the Build → Start Debug → Go option ).
Restart: press Ctrl + Shift + F5. Re-start debugging and execution of the program from the beginning (this is often required after some modifications have been made to the program !). After this option is selected, the system will reload the program to the memory and discard the current value of all variables (and start again ).
Stop Debugging: the shortcut key Shift + F5. Interrupt the current debugging process and return to the normal editing status (note that the system will automatically close the debugger and re-use the Build menu to replace the Debug menu ).
Step Into: the shortcut key F11. Execute the program in one Step, and enter the function when the function call statement is encountered, and execute it from the ground up (the function is the same as that of the Build → Start Debug → Step Into option ).
Step Over: Enter F10. One-step execution of the program, but when the function call statement is executed, it does not enter the function, but directly runs the function after it is executed, and then runs the statement following the function call statement.
Step Out: the shortcut key Shift + F11. Used with "Step Into". When the execution enters the function, several steps are executed in one Step. If you find that you do not need to perform one-Step debugging, this option can be returned from the function (to the next statement of the function call Statement ).
Run to Cursor: press Ctrl + F10. Pause the running of the program to the row where the current mouse cursor is located (Note: before using this option, set the mouse cursor to a line where you want to pause ). In fact, it is equivalent to setting a temporary breakpoint, which is the same as the function of the Build → Start Debug → Run to Cursor option.
Insert/Remove Breakpoint: the shortcut key F9. This menu item does not appear on the Debug menu (in the context context menu of the toolbar and program documentation). It is listed here to help you understand the program debugging methods, its function is to set or cancel a fixed breakpoint. The program line has a circular black dot mark in front of it, indicating that a fixed breakpoint has been set for this row. In addition, Alt + F9 (All Breakpoints in the Management Program) and Ctrl + F9 (disable/enable the current breakpoint) are related to fixed breakpoints ).