Release version error debugging

Source: Internet
Author: User
Tags assert volatile

Often on the CSDN to see someone ask Debug running normally but release failure problem. Previous discussions have tended to be
Empirical, and not to point out what the real cause is, to find out the real reason usually depends on luck. Most
I looked at some of the books in this area, and then took a look at some of the posts on the CSDN, and then studied the two
The difference. Here are some of my experiences and share them with you.
--------------------------------------
This article mainly includes the following content:
1. The essential difference between Debug and release compiling methods
2. In which case the release version will be wrong
2. How to "Debug" release version of the program
--------------------------------------

Discussion on the essential difference between debug and release

The essential difference between Debug and release compiling methods

Debug is often referred to as the debug version, which contains debugging information and does not make any optimizations to facilitate programmer debugging
Order. Release is called a publish version, it is often done with a variety of optimizations that make the program in code size and running speed
are optimized so that users can use them well.
The real secret of Debug and release is a set of compilation options. The following is a list of options for each
(There are, of course, other things, such as/fd/fo, but differences don't matter, and they don't usually cause rele
ASE version error, not discussed here)

Debug version:
/MDD/MLD or/MTD using the Debug Runtime Library (debug version of Run-time function libraries)
/od off optimization switch
/d "_DEBUG" is equivalent to #define _DEBUG, open the Compile debug code switch (mainly for
Assert function)
/ZI create Edit and Continue (edit continue) database so that after debugging
If you modify the source code in the process without recompiling
/GZ can help capture memory errors
/gm to minimize link time by opening a minimized link switch

Release version:
/MD/ML or/MT using the release version of the runtime function library
/O1 or/o2 optimized switch to minimize or speed the program
/d "Ndebug" closes the conditional compilation debug code switch (that is, the Assert function is not compiled)
/GF merges duplicate strings and places string constants in read-only memory to prevent
Be modified

In fact, there is no intrinsic boundary between Debug and release, they are just a collection of compilation options, compiled
The device only acts according to the predetermined options. In fact, we can even modify these options to get the tuned
A trial version or a release version with a tracking statement.

Second, in which case release version will be wrong

With the above description, let's take a look at these options individually to see how release errors are generated

1. Runtime Library: Link which run-time function library usually only has an impact on the performance of the program. Debug version
The Runtime Library contains debugging information and uses some protection mechanisms to help identify errors, so performance
It is better to publish a version. The Runtime Library provided by the compiler is usually stable and does not cause release errors
, because the Debug Runtime Library has tightened detection of bugs, such as heap memory allocations, sometimes
Now Debug error but release normal phenomenon. It should be noted that if debug is wrong, even if the release
Normal, the program must be a Bug, but may be released version of a run did not show it.


2. Optimization: This is the main cause of the error, because the source program when the optimization is turned off is basically directly translated, while playing
The compiler makes a series of assumptions after the optimizations are opened. These types of errors are mainly as follows:

(1) Frame pointer (pointer) ellipsis (FPO): During function call, all call information
(return address, parameters) and automatic variables are placed on the stack. If the declaration of the function is different from the implementation (parameter, return
return value, call mode), you will generate an error ———— but in the Debug mode, the stack accesses through the EBP register
Saved address implementations, and if there are no errors (or "Not many" across the bounds of the array), the function can usually
normal execution; In release mode, optimizations omit the EBP stack base address pointer, which accesses the stack via a global pointer
Will cause a return address error is a program crash. The strongly typed attributes of C + + can check out most of these errors, but as
If you use a forced type conversion, you can't. You can force the/oy-compilation option to be included in release version.
The drop frame pointer is omitted to determine whether this type of error. This type of error is usually:

MFC Message response function write error. The correct should be
afx_msg lresult Onmessageown (WPARAM WPARAM, LPARAM LPARAM);
On_message macros contain coercion type conversions. One way to prevent this error is to redefine the on_message
macros, add the following code to stdafx.h (after #include "AFXWIN.h"), compile when the function is in the wrong prototype
Will complain
#undef on_message
#define ON_MESSAGE (message, MEMBERFXN)/
{message, 0, 0, 0, AFXSIG_LWL,/
(afx_pmsg) (AFX_PMSGW) (Static_cast < Lresult (Afx_msg_call/
CWnd::*) (WPARAM, LPARAM) > (&AMP;MEMBERFXN)},

(2) Volatile variable: volatile tells the compiler that the variable may be modified in an unknown way outside of the program
(such as systems, other processes, and threads). In order to improve the program performance, the optimizer often puts some variables in the register
(similar to the Register keyword), while other processes can only modify the memory in which the variable resides, and the
The value in the device has not changed. If your program is multi-threaded, or you find that the value of a variable does not match what you expect, you
If the letter is set correctly, you are likely to encounter such a problem. This kind of error sometimes manifests as the program in the quickest optimization out
Wrong and minimal optimization normal. Try to add volatile to the variable you think is suspicious.

(3) Variable optimization: The optimizer optimizes variables based on the use of variables. For example, one of the functions has not been
The variable that is used in the Debug version may mask an array out of bounds, while in release, the variable
is likely to be tuned, when the array is out of bounds, which destroys useful data in the stack. Of course, the actual situation would be more complicated than this.
Many. The errors associated with this are:
Illegal access, including array bounds, pointer errors, and so on. For example
VOID fn (void)
{
int i;
i = 1;
int a[4];
{
Int J;
j = 1;
}
A[-1] = 1;//Of course the error is not so obvious, such as subscript is a variable
A[4] = 1;
}
Although the scope of the array has been out of bounds, but the space has not been retracted, so I and J will cover the more
Territories. and release version because I, J does not have a great effect may be optimized out, so that the stack is destroyed.

3. _DEBUG and Ndebug: When _DEBUG is defined, the Assert () function is compiled, and Ndebug does not
Be compiled. In addition, VC + + also has a series of assertion macros. This includes:

ANSI C assertion void assert (int expression);
C Runtime Lib Assertion _assert (booleanexpression);
_asserte (booleanexpression);
MFC assertion assert (booleanexpression);
VERIFY (booleanexpression);
Assert_valid (Pobject);
Assert_kindof (classname, pobject);
ATL Assertion Atlassert (booleanexpression);
In addition, the compilation of TRACE () macros is also controlled by _DEBUG.

All of these assertions are compiled only in the debug edition and are ignored in release editions. The only exception is
VERIFY (). In fact, all of these macros invoke the Assert () function, but attach some library-related
Debugging code. If you add any program code to these macros, not just Boolean expressions (such as assigning values,
Change the value of a function call, etc.), then release version will not perform these operations, resulting in errors. Early
Academics are apt to make such mistakes, and the search method is simple because these macros are listed above, as long as the V
C + + found in the Files feature in all of the project to find a place to use these macros to check again. Other than that
, some experts may also join #ifdef _DEBUG and other conditions such as compiling, but also pay attention to.
Incidentally, it is worth mentioning the VERIFY () macro, which allows you to place the program code in a Boolean expression. This one
Macros are typically used to check the return value of the Windows API. Some people may abuse VERIFY for this reason (), the fact
This is dangerous because VERIFY () violates the idea of assertions and cannot completely separate the program code from the debug code
, it could end up being a lot of trouble. Therefore, experts recommend that you use this macro as little as possible.

4./GZ option: This option will do the following

(1) Initialize memory and variables. Includes initialization of all automatic variables with 0xCC, 0xCD (cleared Data
Initializes the allocated memory in the heap (that is, dynamically allocated memory, such as New), 0xDD (Dead Data) padding
Heap memory that has been freed (for example, delete), 0xFD (DEFENCDE Data) initializes protected memory (DE
The bug version adds protected memory before and after dynamically allocating memory to prevent cross-border access, where the words in parentheses are Microsoft built
Words of help. The advantage of this is that these values are large, as pointers are not possible (and the 32-bit system middle finger
Needles are rarely singular values, and in some systems odd pointers produce run-time errors, and are rarely encountered as numeric values.
And these values are easy to identify, so it's good to see the release version in the Debug version.
Miss. It is particularly important to note that many people think that the compiler will initialize the variable with 0来, which is wrong (and so
is not conducive to finding errors).
(2) when calling a function through a function pointer, the matching of function calls is validated by checking the stack pointer. (Prevent the original
form does not match)
(3) Check the stack pointer before returning the function to confirm that it has not been modified. (Prevent Cross-border access and prototype mismatch, with the second
Items are combined to roughly simulate frame pointer ellipsis FPO)

Usually the/GZ option causes the Debug version to go wrong and the release version is normal, because in release
Uninitialized variables are random, which may cause the pointer to point to a valid address and mask illegal access.

In addition,/GM/GF and other options cause fewer errors, and their effects are obvious and easier
Found.

Third, how to "Debug" release version of the program

It is obviously frustrating to encounter Debug success but release failure, and it is often impossible. Such as
You see the above analysis, combined with the specific performance of the error, quickly found the error, is very good. But if you find
No, here are some strategies in this case.

1. As mentioned earlier, Debug and release are just a set of compilation options, and there is actually nothing
Definitions can distinguish between the two. We can modify the release version of the compilation options to narrow the error range. As mentioned above, you can
Change the release options to the corresponding Debug option, such as/MD to/MDd,/o1 to/od
, or run time optimization to program size optimization. Note that only one option is changed at a time, and the error is eliminated when changing the option
Lost, and then the error related to the option should be targeted to find. These options are in the project/settings ... In all can
To select directly from the list, usually without manual modification. Since the above analysis has been quite comprehensive, this method is most
Effect of.

2. In the programming process should always pay attention to test release version, lest the final code too much, time is very tight.


    3. Use the/W4 warning level in the Debug edition to get the maximum error information from the compiler,
such as if (i = 0), which can cause/w4 warnings. Do not ignore these warnings, which are usually caused by bugs in your program
. But sometimes/w4 can bring a lot of redundant information, such as unused function parameter warnings, and many message handler functions
Ignore certain parameters. We can use the
      #progma Warning (disable:4702)//disable
     //...
      #progma Warning (default:4702)//re-allow
to temporarily prohibit a warning, or use the
      #progma Warning ( Push, 3)//Set warning level to/W3
     //...
      #progma warning (POPs)//reset to/W4
to temporarily change the warning level, sometimes you can use/W4 only in the part of the code that you think is suspicious.

    4. You can also debug your release version like Debug, just by adding debug symbols. In project/s
ettings ... , select the Settings for "Win32 release", select the C + + tab, and Category select
General,debug Info to select program Database. Then in the Link label Project options finally
Add "/opt:ref" (Don't lose the quotes). This allows the debugger to use debug symbols in the PDB file. However, when you debug
you will find that breakpoints are difficult to set, and variables are hard to find--all of which have been optimized. Thankfully, the Ca
ll Stack window is still working, even though the frame pointer is optimized, stack information (especially the return address) can still be found
. This is helpful for locating errors.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.