VC Debug Version and Release Version

Debugging is the process of correcting or modifying code so that it compiles and runs smoothly. To this end, VC IDE provides powerful debugging and tracing tools.

1.1.1  Debug Version and Release Version

The development environment always creates debug and release versions of your project. In the debug version, we troubleshoot all possible program errors, and then make a release version to get better information. This is the difference between the debug version and the release version: the former contains more debugging information, the final execution file is larger, and the performance is poor; the latter final execution file is smaller and the performance is better. Specifically, the differences between the release version and the debug version are:

1.        In the debug version, you can use diagnostic and trace macros, such as ASSERT and TRACE , and the DUMP function of the MFC class is also defined in the debug version.

2.        Additional variable initialization. The compiler will automatically assign your uninitialized variables to 0xCC byte by byte .

3.        Memory allocation monitoring. In the debug version, the memory allocated on the heap will be recorded and additionally initialized (0xCD) , and its content will be set to 0xFD byte by byte when it is released .

How do I configure a debug [C1] or release version? 

Both debug and release builds can be added from  Build | Configurations , or from the Project | Settings command when both configurations already exist . The two main differences in configuration are as follows:

1.  The two versions should be configured into different output folders. This is set in the two edit boxes in Project | Settings | General .

2.  Under the debug version, the program should link the Debug version of the c runtime library, disable code optimization, and add the predefined identifier _DEBUG to the Preprocessor category in the C++ property page . In the Debug category in the Link property page , check the DebugInfo and Microsoft Format checkboxes.

4.        Under the release version, the program should link the C runtime library of the Release version , set the code optimization, do not define the _DEBUG identifier, and remove the selection in the DebugInfo check box.

1.1.2  Eliminate compilation errors

The VC6.0 compiler can report about 1100 or so errors, not including warnings. In the process of compiling and debugging, we not only encounter compilation errors, but also link errors and other errors, so we can only talk about some very common and important compilation errors. The best way to fix a compile error that we didn't list is to position the cursor on the output line in the output window and press F1 for help from MSDN . If the version of MSDN is not compatible with your VC , then you can search in MSDN with getting Error xxxx as the keyword . Help for these errors currently appears under the Build Errors entry in the Visual C++ Programmer's Guide .

not an error

Reports like " Loaded 'C:\WINNT\system32\gdi32.dll', no matching symbolic information found. " are not errors. In general, we just need to trace our own source code and check what went wrong there. But sometimes we also want to see what happens if a bug is reported in a system DLL . Microsoft is reluctant to include debug information in system DLLs , so it provides debug symbols to help you track down. There is a debug symbols package distributed with VC6.0 , but its contents may not keep up with your OS version. If you need debug symbols for your OS version, please download them from the Microsoft Update site.

l        LNK2001 error

LNK2001 error reporting an unrecognized external identifier. Usually when you use a function or external variable, you must give its declaration in advance, otherwise such an error will occur. The reasons can be found from the following aspects:

1.        Use an inline function, but the inline function is defined in the .cpp file, not in the .h file.

2.        Functions or external variables were declared, but their definitions could not be found.

3.        The program entry setting is wrong, and further prompts _WinMain@16': Unresolved External Symbol or similar errors. In a Windows program, the program does not first start execution from functions such as WinMain() or Main() , but from WinMainCRTStartup () or MainCRTStratup functions. These four functions (actually 8 , each with UNICODE and single-byte versions) must match. If the entry point is WinMainCRTStartup() , it expects to find a WinMain() function in your program, if not, the above error occurs.

4.        The thread start function _beginthread is used in the program , but the selected link library is LIBC.LIB .

See MSDN for other errors .

1.1.3  Breakpoints and Traces

Compilation errors are all static, more errors occur at runtime. To troubleshoot runtime errors, the first thing you need is to be able to stop the running code. VC6.0 provides a variety of breakpoint settings.

l        Location breakpoint

l        Conditional breakpoint: You can set the following conditions to be true to interrupt the program

1.        When the value of a single variable changes

2.        Single variable value judgment condition is interrupted, such as K>0 , i == 5 , etc.

3.        The value of a single element or multiple elements of the array is changed or the value judgment condition is interrupted.

4.        Pointer: the pointer variable changes or the content pointed to by the pointer changes

5.        Monitor fixed memory value changes

6.        Monitor the change of the value in the register, such as  cs == 0 , etc.

You can also enter a breakpoint setting expression directly, the syntax is:

 Detailed explanation of Advanced Syntax

{[function],[source],[exe] } location

{[function],[source],[exe] } variable_name

{[function],[source],[exe] } expression

 

Enclosed in {} pairs is the context setting, any of these three items can be omitted, but when omitting the preceding items, you should pay attention to keep the comma. as the following settings

it's wrong:

{File.c, File.exe} .143 - Bad

Correct settings such as

{Fun}.143 This sets a breakpoint at line 143 of the  function Fun .

 

See the example below for a more detailed explanation:

{[function],[source],[exe] }  .100 - A line number (this may not work with some languages)

{[function],[source],[exe] }  @100 - A line number (this works for all languages)

{[function],[source],[exe] }  Traverse - A function name

{[function],[source],[exe] }  CMyWindow::OnCall - A function name

{[function],[source],[exe] }  00406030 - A memory address (decimal)

{[function],[source],[exe] }  0×1002A - A memory address (hexadecimal)

{function,[source],[exe] }     Label - A statement label. The context must include function since

Label is visible in the function’s scope.

 

For more detailed help, see the Setting Breakpoints When Values ​​Change or Become True topic in the Visual C++ Programer's Guid .

lMessage        breakpoint

lException        breakpoint

When an exception occurs in the program, we should immediately stop and see what happened. By default, when an exception occurs, the Debugger  writes the exception information to the Output  window, and according to your choice, decides whether to interrupt the program immediately. This setting is available in the Exceptions option in the Debug menu . Two options , Stop Always and Stop If Not Handled , are provided here . When Stop If Not Handled is selected, the debugger just outputs a message to the Output window, and does not abort the program, unless the exception is not handled in the end. In some cases, this will be a bit late. When Stop Always is selected, the debugger will interrupt the program before the exception handling code takes over.

1.1.4  View and modify the running status of the program

The development environment provides a series of viewing methods to view and even modify the running state of the program. A total of six viewing windows are provided:

l        Watch window

The Watch window is used to view and decode intermediate variables and allow you to modify the value of the variable. There are four Tabs in the Watch window . Each Tab is a ListView , consisting of two columns. The left column is the variable name, and the right column is the variable value. As long as you enter the variable name in the variable name column and press Enter, you can get the value of the current variable. Here are some special usages:

1.        List the values ​​of the first n elements in an array: arr , n

2.        View the UNICODE encoded string value: str , su

3.        Know the message value, check the corresponding macro: messageValue , wm

4.        View the window class flag ( Window class flag ): flagValue , wc

5.        View the last bug report of the current thread: @err , hr

6.        Check the COM library last bug report: @hres,hr

7.        View the current register value and input the register name as the variable name.

Entering a new value directly in the right column will modify the value of the variable and take effect.

l        Variables window

This window keeps track of important variable values ​​in the current context. But can not increase the tracking of variables. It contains three Tabs :

The Auto window keeps track of variables used in the current declaration or the previous declaration, and can also display the function's return value when you step out of a function call.

The Locals window displays the values ​​of variables that are local to the current function.

The This window displays the value of the object pointed to by the this pointer.

In addition, in the upper part of the Variables window, there is a Context combo box that can be used to switch the currently viewed context.

l        CallStack window

This window shows what the function calls are like. When an assertion occurs in your program, you can use this window to call out the function call sequence, and you can know what parameters are passed when calling. Double-click a function listed in the window to navigate to the source code.

l        Memory window

The upper part of the Memory window is an address input box. You can enter 0x00400000 here , because this is the starting point of the process, so it is not surprising that you will see the words MZ . The Memory window supports custom display formats and supports expressions.

Right-clicking on the lower window of the Memory window brings up a menu that allows you to display the contents of the memory in single-byte, double-byte hex or four-byte hex.

There are ways to get a more accurate display, if you're willing to go to the trouble. Click Tools | Options , select the Debug property page, where you can decide what form to display the memory content and from what address to display. There are 14 format options available here. Additionally, you can enter an address expression. For example, if you want to know what the current top of the stack is, enter ESP here .

l        Disassembly window

This window can be used to trace optimized code, or complex expressions.

l        Registers window

The Registers window displays all register values ​​and allows you to modify them. The difference between it and the Watch window is that you don't need to remember register names, it always lists all register values ​​for you.

1.1.5  Using assertions and diagnostics [1]

VC provides two assert macros: ASSERT and VERIFY . The difference between the two is that in the release version the ASSERT line is not executed because in the release version the ASSERT macro is defined as

#define ASSERT /##/

This line of code is commented out so that it won't compile. The VERIFY macro is defined in the distribution as

#define VERIFY

In this way , the code behind VERIFY is still compiled and executed.

After you grasp the difference between these two assertions, we will only cover the ASSERT macro. ASSERT is a parameterized macro whose parameter is allowed to be an expression. When the expression evaluates to false, the program breaks and prompts you to debug.

In addition to using conditional judgment expressions, ASSERT(0) is also useful. It always raises an assertion error and prompts you to debug. You can put it on some path that you don't expect the program to run to, and if something happens, you can directly debug it.

VC also provides the TRACE macro, and its sister macros TRACE0 , TRACE1 , TRACE2 , TRACE3 . The syntax of the TRACE macro is similar to that of printf , including the same specification of format strings. The last three macros qualify you to use a format string and one to three variables. TRACE is output to the Output window, if enabled in the tool MFC TRACER .

MFC also provides an object diagnostic tool, a function called Dump . Every class in the MFC library that inherits from CObject has the ability to Dump . If you derive a class from the MFC class library, it is best to override this function if necessary. Remember that your overloaded function should call the base class's Dump function. Also, the Dump function is only available in the debug version. So overloaded functions should also be enclosed in the #ifdef _DEBUG macro.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325691042&siteId=291194637