Debugging techniques used in C language vs. Visual Studio

Table of Contents

1. What is a bug?

2. What is debugging? Why is debugging important?

2.1 Basic steps for debugging

2.2 Introduction to Debug and Release

3. Introduction to debugging in Windows environment

3.1 Preparation of debugging environment

3.2 Learn the shortcut keys

3.3 Edit shortcut keys

3.4 Check the current information of the program during debugging

3.3.1 View the value of temporary variables

At this point we can observe the changes in a and b at each step

3.3.2 View memory information? Edit

?edit

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

4.1 How to write code that is easy to debug

4.1.1 Using assert

4.1.2 Using const

5. Common programming mistakes

5.1 Compilation errors

5.2 Linked errors

5.3 Runtime errors


C language has always been the first choice for programmers because it is a low-level language that can directly access the computer’s memory and hardware resources. Visual Studio (VS) is a powerful integrated development environment (IDE) that provides developers with a wealth of tools and functions. In C language development, debugging is a crucial link. In this article, we’ll explore debugging tips for using C with Visual Studio to make diagnosing and solving problems easier.

1. What is a bug?

In the C language, a “bug” refers to an error, defect, or unexpected behavior in a program. Bugs can cause a program to run incorrectly, crash, or produce unexpected results. Bugs can include various types of problems, such as syntax errors, logic errors, runtime errors, memory leaks, performance issues, etc. Typically, one of the programmers’ tasks is to identify and fix these bugs to ensure the correctness and stability of the software.

2. What is debugging? Why is debugging important?

Debugging is the process of identifying and fixing bugs in a program. During software development, errors are almost inevitable. These errors may be syntax errors, logic errors, runtime errors, or various other issues. Debugging is a critical step in identifying, locating, and fixing these issues. Without proper debugging skills, it will be difficult for developers to find problems and fix them, which may lead to a decrease in the quality of the software and even affect the user experience.

2.1 Basic steps for debugging

(1) Reproduce the problem and determine that there is a problem in the program

(2) Understand the problem and determine the nature and location of the problem

(3) Find problems and find specific problem locations by setting breakpoints, single-step execution, observing variables, etc.

(4) Analyze and solve problems, find the root problems and solve them

(5) Retest, after making repairs, rerun the program to ensure that the problem has been solved

2.2 Introduction to Debug and Release

Debug version:

(1)Purpose: The Debug version is mainly used in the development and debugging phases, aiming to help developers identify and fix problems in the code.

(2) Features: The Debug version usually includes debugging information, allowing developers to track the execution of the program in the debugger, view the values of variables, set breakpoints, etc. Additionally, code optimization is often not done to make the code easier to understand and debug.

(3) Performance: The Debug version usually runs slower because it contains additional debugging information and unoptimized code.

(4) Maintainability: Because it contains detailed debugging information, the Debug version is more maintainable, but the file size is larger.

Release version:

(1) Purpose: Release version is used in actual deployment and production environments. It is designed to provide end users with the best performance and minimal resource usage.

(2) Features: Release versions usually have code optimization to improve the execution efficiency of the program. At the same time, it usually removes debugging information to reduce the size of the executable file and thereby reduce resource usage.

(3) Performance: Release version usually runs faster because it has been optimized by the compiler and linker and does not contain debugging information.

(4) Maintainability: Release version is less maintainable because it removes debugging information, making it difficult to diagnose and solve problems in a production environment.

3. Introduction to Windows 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 shortcut keys

Some of the most commonly used debugging shortcut keys:

F5

Start debugging, often used to jump directly to the next breakpoint.

Note: How to set breakpoints

F9

Create and cancel breakpoints
The important role of breakpoints 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.

Just click anywhere on the line where you want a breakpoint and press F9.

In addition, there is a simpler way

Just click the left mouse button on the leftmost position of the line that needs a breakpoint.

F10

Process-by-process is usually used to process a process. A process can be a function call or a statement.

F11

Statement-by-statement means executing one statement each time, but this shortcut key allows our execution logic to enter the function (this is the most commonly used).

Such as the following string of code (the header file is omitted)

void Print(int n) {
if (n > 9) {
Print(n/10);
printf("%d ", n % 10);
}
}
 
int main() {
int n;
scanf("%d", & amp;n);
Print(n);
return 0;
}

This string of code is used to print each bit of an integer recursively.

Start stepping through code when we press F10 (or F11)

When we continue to press F10 (or F11), the arrow moves downward. When we reach line 168, we enter any integer. When we reach the Print (n) function, if we continue to press F10, the result we get is

At this point we found that it directly completed the entire function calling process

But if we go to the Print(n) function, we press F11

At this point we find that the arrow has entered the Print function. If we continue to press F11, it will be executed step by step within the Print function statement by statement.

CTRL + F5

Start execution without debugging. If you want the program to run directly without debugging, you can use it directly.

3.3Edit shortcut keys

When writing code, familiarity with some editing shortcut keys can also help us complete the code better.

Shift + Alt + Enter: Toggle full screen editing

Ctrl + U: Change all to lowercase

Ctrl + Shift + U: Change all to uppercase

Ctrl + Shift + V: Clipboard cycle (you can directly see the results of the most recent copies)

Ctrl + Shift + L: Delete the current line (all text codes on the line will also be deleted)

Ctrl + K + C: Annotate the selection

Ctrl + K + U: Uncomment the selection

3.4 Check the current information of the program during debugging

3.3.1 View the value of temporary variables

Observe the value of variables while debugging

In this code, if we need to observe the values of a and b after each step is executed, we can enter them in the monitor

At this time we can observe the changes at a and b at each step

3.3.2 View memory information

At this point here we can see the address of a and the value of a

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

Be sure to master debugging skills.
Beginners may spend 80% of their time writing code and 20% of their time debugging. But a programmer may spend 20% of his time writing
program, but 80% of the time is debugging.
Very complex debugging scenarios may occur in the future: debugging of multi-threaded programs, etc.
Use shortcut keys more to improve efficiency.

4.1 How to write code that is easy to debug

4.1.1 Use assert

#include <assert.h">
void assert( int expression );

The function of assert is to evaluate the expression expression. If its value is false (that is, 0), then it first prints an error message to stderr, and then terminates the program by calling abort.

For example, if the values of a and b are equal in this code, it means that no subsequent exchange steps are needed, so an error will be reported directly.

If assert is called frequently, it will greatly affect the performance of the program and add additional overhead.

After debugging, you can disable assert calls by inserting #define NDEBUG before the statement containing #include

4.1.2 Use const

When const modifies pointer variables:

1. If const is placed on the left side of *, it modifies the content pointed by the pointer, ensuring that the content pointed by the pointer cannot be changed through the pointer. But the content of the pointer variable itself is mutable.
2. If const is placed on the right side of *, it modifies the pointer variable itself, ensuring that the content of the pointer variable cannot be modified, but the content pointed to by the pointer can be changed through the pointer.

#include <stdio.h>
//Code 1
void test1()
{
int n = 10;
int m = 20;
int *p = &n;
*p = 20;//ok?
p = & amp;m; //ok?
}
void test2()
{
//Code 2
int n = 10;
int m = 20;
const int* p = & amp;n;
*p = 20;//ok?
p = & amp;m; //ok?
}
void test3()
{
int n = 10;
int m = 20;
int *const p = & amp;n;
*p = 20; //ok?
p = & amp;m; //ok?
}
int main()
{
//Test without cosnt
test1();
//The test const is placed to the left of *
test2();
//The test const is placed on the right side of *
test3();
return 0;
}

Q: Think about where in the above code an error will be reported

5. Common programming errors

5.1 Compilation Error

Look directly at the error message (double-click) to solve the problem. Or you can do it with experience. Relatively simple.

5.2 Linked Error

Look at the error message, mainly find the identifier in the error message in the code, and then locate the problem. Usually the identifier name does not exist or is spelled incorrectly.

5.3 Runtime Error

Use debugging to locate the problem step by step.