C language--Practical debugging skills

1. Is thisbug?

        A "bug" is an error or defect in a computer program or system. It can cause a program to not function as expected, producing unexpected behavior or erroneous results.

Bugs can appear in a variety of different situations, such as:

1. Grammatical errors: This is the most common type of error, usually caused by spelling errors, missing semicolons, mismatched brackets, etc.

2. Logic errors: This type of error occurs in the logical flow of the program, causing the program to fail to process data correctly or perform expected operations under certain circumstances.

3. Memory errors: Memory errors occur when a program accesses unallocated memory, frees allocated memory, or accesses freed memory.

4. Concurrency errors: When multiple threads or processes access shared resources at the same time, concurrency errors, such as race conditions, deadlocks, etc., may occur.

5. Algorithm error: This error usually occurs when the wrong algorithm or data structure is used in the program, causing the program to be unable to process the data correctly.

        To resolve bugs, developers often use debugging tools and techniques to locate and fix errors. This may include using breakpoints, log output, code review, etc. to trace the execution of the program and find the problem. Fixing bugs often requires modifying and retesting the code to ensure that the problem is resolved and new errors are not introduced.

 2. What is debugging? How important is it?

Everything that happens must be traceable. If you have a clear conscience, there is no need to cover up and there will be no traces. If you have a clear conscience,
It must be covered up, then there must be signs.The more signs there are, the easier it is to follow. This is the way of reasoning.
Going down this path is crime, going upstream is the truth.
A good programmer is a great detective.
Every debugging is a process of trying to solve a crime.

2.1 What is debugging?

Debugging (English: Debugging / Debug), also known as debugging, is the discovery and reduction of computer programs or programs in electronic equipment.
A wrong process.

2.2 Basic steps for debugging

1. Discover the existence of program errors
2. Locate errors by means of isolation, elimination, etc.
3. Determine the cause of the error
4. Suggest solutions to correct errors
5. Correct program errors and retest

2.3 DebugRelease's intervention.  

Debug is often called the debug version, which contains debugging information and does not make any optimizations, making it easier for programmers to debug programs.
Release is called a release version. It often carries out various optimizations to make the program optimal in terms of code size and running speed so that users can use it well. .

 

 Requirements --> Design and development --> Testing --> Product acceptance --> Release

Testers test the release version.

Next let's look at a piece of code:

#include <stdio.h>

int main() {

    int arr[5];
    for (int i = 0; i < 5; i++) {
        arr[i] = -1;
    }

    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }

    return 0;
}

 We can clearly see the difference in size between the two. The reason is that theDebug version has not been optimized.Release has been optimized.

Summarize:

Debug version and Release version refer to different construction methods in the software development process. The differences between them are as follows:

1. Compiler optimization: In the Debug version, the compiler usually does not perform optimizations to make it easier to debug the program, while in the Release version, the compiler performs various optimizations to improve the running efficiency of the program.

2. Debugging information: In the Debug version, the compiler will contain a large amount of debugging information, such as variable names, function names, line numbers, etc., to make it easier to debug when debugging the program. In the Release version, the compiler will usually Remove this debugging information to reduce program size and improve running efficiency.

3. Error checking: In the Debug version, the compiler will perform various error checks, such as array out-of-bounds, null pointer, etc., to make it easier to find errors when debugging the program. In the Release version, the compiler will usually delete these errors. Check to improve the running efficiency of the program.

4. Performance: Because the Debug version contains a lot of debugging information and error checking, it usually runs slower than the Release version, while the Release version is usually faster.

In general, the main difference between the Debug version and the Release version lies in debugging information, error checking and compiler optimization. During the development process, we usually use the Debug version for debugging and testing, and when releasing products, we use the Release version to improve the running efficiency of the program and reduce the size of the program.

3. WindowsIntroduction to environment debugging

3.1 Preparation of debugging environment

 Only by selecting the debug option in the environment can the code be debugged normally.

3.2 Learn the shortcut keys

Some of the most commonly used shortcut keys:

F5: Start debugging, often used to jump directly to the next breakpoint.
F9: Create and cancel breakpoints

        Breakpoints The important role of is to set breakpoints anywhere in the program.
        This allows the program to stop execution at the desired location and continue executing step by step.
(Generally, F5 and F9 are used together.

F10: Process by process, usually used to process a process. A process can be a function call or a statement.
F11: Statement by statement, that is, executing one statement each time, but this shortcut key can make our execution logic enter the inside of the function (This is the most commonly used).
Ctrl + F5: Start execution without debugging. If you want the program to run directly without debugging, you can use it directly.

 It is worth mentioning that when using F9, we can set conditional breakpoint:

        A conditional breakpoint is a breakpoint set during debugging that only triggers the breakpoint when certain conditions are met. By using conditional breakpoints, you can control the execution flow of your program more precisely and stop your program under specific conditions for debugging.

        When the program executes to the breakpoint position where the condition is set, the debugger will evaluate the conditional expression. Ifthe condition is true, the breakpoint will trigger and the program will pause execution to allow you to debug. If the condition is false, the program will continue executing normally without triggering the breakpoint.

        Conditional breakpoints are very useful for debugging under specific conditions, such as when the value of a variable reaches a specific threshold, whether a specific condition is met, etc. They can help you debug and locate problems more efficiently.

Setting conditional breakpoints 

 

3.3 ​​View the current information of the program during debugging

3.3.1 View the value of temporary variable

Used to observe the value of a variable after debugging has started.
Set breakpoint, After pressing F10-- 

3.3.2 View memory information

Used to observe memory information after debugging starts.

3.3.3 View call stack

Through the call stack, the calling relationship of the function and the location of the current call can be clearly reflected.

 

3.3.4 Check out the information

 After debugging starts, there are two ways to go to assembly:

(1) The first method: right-click the mouse and select [Go to Disassembly]:

 

 2) Second way: You can switch to assembly code.

 3.3.5 View register information

 4. Only by doing more and trying debugging can you make progress

5. Some debugging examples

 5.1 Example 1

Implementation code: Ask for 1! +2! +3! +...+n! ; Overflow is not considered.

int main() {
int i = 0;
int sum = 0;//保存最终结果 
int n = 0;
int ret = 1;//保存n的阶乘 
scanf("%d", &n); 
for(i=1; i<=n; i++)
{
   int j = 0;
   for(j=1; j<=i; j++)
        {
          ret *= j; 
        }
   sum += ret; 
}
    printf("%d\n", sum);
    return 0; 
}

         It’s obvious that something went wrong!

        Through debugging, we found that when calculating the factorial of 3, the result should be 6, but here it is 12. We can think that the reason is that ret is not initialized when starting the loop, causing ret itself to have a value.

        After initializing ret, the result is indeed correct!

5.2 Example 2

#include <stdio.h>
int main() 
{
    int i = 0;
    int arr[10] = {0};
    for(i=0; i<=12; i++)
    {
        arr[i] = 0;
        printf("hehe\n");
    }
return 0; 
}

        After running, an infinite loop prints hehe, why?

 

 

        After debugging, we found that when the array went out of bounds, the program was still running. Finally, when i=12, arr[12] = 0. At this time, i was also 0. By looking at the addresses of arr[12] and i, we found two If the two addresses are the same, arr[12] is 0, and i will also be 0, which causes the program to continue looping.

Underlying logic: 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/2301_76618602/article/details/132049372