This page
DEBUG and RELEASE Compile Essential differences In the case of the Release version, how to "debug" Release version of the process
DEBUG and RELEASE Compile Essentially DEBUG is often referred to as debug version, which contains debugging information, and does not make an optimization, which is convenient for programmer debugging. Release is called publishing, which is often optimized so that the program is optimal in code size and running speed so that users are well used.
Debug and Release True Secrets lies in a set of compilation options. The following is listed below (otherwise additional, such as / fd / fo, but the difference is not important, usually don't cause the Release version error, not discussing here)
Debug version parameter meaning / MDD / MLD or / MTD Using Debug Runtime Library (debug version runtime function library) / OD close Optimization switch / D "_debug" is equivalent to #define _debug, open the compile debug code switch (mainly for the ASSERT function " ) / Zi Create Edit and Continue Database, so if the source code is modified during the debugging process No need to recompile / GZ can help capture the memory error / GM to open the minimum reduction chain switch, reduce the link time
Release version parameter meanings / MD / ML or / MT uses the release version of the runtime function library / O1 or / O2 optimization switch, make the program minimum or the fastest / D "nDebug" close condition compile the debug code switch (ie, do not compile the Assert function " ) / GF combined repetitive strings and put strings constants in read-only memory to prevent modification
In fact, Debug and Release have no essential boundaries, they are just a set of compile options, and the compiler is just a scheduled option action. In fact, we can even modify these options to get an optimized debug version or a publishing version with tracking statements.
Back to top
In this case, the release version has an error with the above introduction, let's take a look at these options to see how the Release version is generated.
1. Runtime Library: Which runtime library is usually only impact on the performance of the program. The debug version of Runtime Library contains debugging information and has some protection mechanism to help find errors, so performance is not as good as release. The Runtime Library provided by the compiler is usually very stable and will not cause the Release version of the error; It should be pointed out that if Debug is wrong, even if Release is normal, the program is definitely a bug, but it may be that the release version of the RELASE version is not expressed. 2. Optimization: This is the main reason for errors, because the source program is basically directly translated, while the compiler will make a series of assumptions after opening optimization. Such errors have the following:
1. Frame Pointer omission (referred to as FPO): During the function call, all call information (return addresses, parameters), and automatic variables are placed in the stack. If the declaration of the function is different (parameters, return value, call mode), an error is generated --- but DEBUG mode, the stack is implemented through the address saved by the EBP register, and if there is no error, the error occurred (Or the crossover "not much"), the function can usually be executed properly; Under the Release mode, the EBP stack base pointer is omitted so that the return address error will cause the return address to crash through a global pointer access stack. C strong type features can check most such errors, but if they use forced type conversion, they will not. You can enforce the Add / Oy-Compile option in the Release version to turn off the frame pointer to determine if this class is. Such errors are usually: • MFC message response function writing errors. The correct should be: AFX_MSG LRESULT OnMessageown (WPARAM WPARAM, LPARAM LPARAM); ON_MESSAGE macro includes mandatory type conversion. One of the methods to prevent this error is to redefine the ON_MESSAGE macro, add the following code into stdafx.h (after #include "afxwin.h"), the function is compiled when compiling. #undef on_Message
#define on_Message (Message, MemberfxN) /
{Message, 0, 0, 0, AFXSIG_LWL, /
(AFX_PMSG) (AFX_PMSGW) (static_cast CWnd :: *) (WPARAM, LPARAM)> (& MemberfxN)} 2. Volatile type variable: Volatile tells the compiler that the variable may be modified in an unknown manner outside the program (such as system, other processes, and threads). Optimization procedures in order to increase program performance, some variables are often placed in registers (similar to the register keyword), while other processes can only modify the memory where the variable is located, and the value in the register has not changed. If your program is multi-thread, or you find that the value of a variable does not match the expected, you are confident that it is set, it is likely to encounter such problems. This error sometimes manifests the program to optimize the normal optimization in the fastest optimization. Try the VOLATILE that you think is suspicious. 3. Variable Optimization: The optimization program optimizes the variables according to the use of the variable. For example, there is a variable that is unused in the function, which is likely to cover a array base, and in the Release version, this variable is likely to be optimized, and the array crosstation will destroy the data used in the stack. Of course, the actual situation will be much more complicated than this. There are errors related to this: • Illegal access, including array offline, pointer error, etc. For example void fn (void) { INT I; i = 1; Int a [4]; { Int J; J = 1; } A [-1] = 1; // Of course, the error will not be so obvious, such as the subscript is a variable. a [4] = 1; } J Although the scope has been used in the array of crosses, the space has not been retracted, so I and J will cover the offline. And Release Edition Due to I, J does not have a big role to be optimized, so that the stack is destroyed. 3. _debug and ndebug: When _debug is defined, the assert () function is compiled, while NDebug is not compiled. In addition, there is a series of assertion macros in VC . This includes: assertion type defined in ANSI C assertion void assert (int expression); C Runtime Lib assertion _ASSERT (booleanExpression); _ ASSERTE (booleanExpression); MFC assert ASSERT (booleanExpression); VERIFY (booleanExpression); ASSERT_VALID (pObject); ASSERT_KINDOF ( ClassName, POBJECT; ATL asserts Atlassert (BooleaneXpression); In addition, the compilation of the Trace () macro is also controlled by _debug. All of these assertions are only compiled in the Debug version, and it is ignored in the release version. The only exception is verify (). In fact, these macros are calling the assert () function, but there are only some debugging code related to the library. If you add any program code in these macros, not just Boolean expression (such as assigning, you can change the variable value of the variable value), then the Release version does not perform these operations, resulting in an error. Beginners are easy to make such mistakes, the method of finding is also very simple, because these macros have been listed above, as long as the VC Find in Files feature is used to find these macros in all files, then check can. In addition, some masters may also join the criteria compilation of #ifdef _debug, but also pay attention to it. By the way, it is worth mentioning the verify () macro, this macro allows you to put the program code in the Boolean expression. This macro is usually used to check the return value of the Windows API. Some people may abuse verify () for this reason, in fact this is dangerous, because verify () violates the idea of asserting, can't completely separate the program code and debug code, and ultimately may bring a lot of trouble. Therefore, experts recommend that this macro is used as much as possible. 4. / GZ option: This option will do these things: 1. Initialize memory and variables. Including all automatic variables, 0xCD (ie, dynamically assigned memory, such as new), 0xDD (DEAD DATA), 0xFD (DEFENCDE), 0xCD (DEFENCDE), 0xFD (DEFENCDE) DATA) Initializing the protected memory (DEBUG version is added to prevent memory before and after dynamic allocation to prevent offshore access), where the words in the parentheses are a help letter proposed by Microsoft. The benefits of doing this are that these values are very large, and it is impossible as a pointer (and the pointer in the 32-bit system is rarely odd, and the odd pointer in some systems will generate runtime errors), as a few more It is also easy to identify, so this is also very beneficial to find the error that Release version will encounter in the Debug version. It is important to note that many people think that the compiler will use 0 to initialize the variable, which is wrong (and this is very disadvantage). 2. When the function is called by the function, the function call is verified by checking the stack pointer. (Preventing the original shape does not match) 3. The function returns the front inspector pointer and confirmed that it was not modified. (Prevent Offshore Access and Original Mismatch, with the second one can be rushed to the frame pointer to omit the FPO) usually / gz option causes the Debug version error and the normal phenomenon of the Release version, because the unmelted variables in the release version are randomly It is possible to make the pointer to cover an effective address to cover illegal access. In addition, / GM / GF and other options have less errors, and their effect is obvious, it is easier to find. Back to top How to "debug" Release version of the program encountered DEBUG success but Release failed, it was obviously a very frustrated thing, and often without starting. If you look at the above analysis, combine the specific performance of the mistake, soon find a mistake, although very good. But if you can't find it for a while, some strategies in this case will be given. 1. Before mentioned, Debug and Release are only the difference in compilation options, and there is no definition that can distinguish between them. We can modify the Release version of the compilation option to narrow the range of error. As mentioned above, the release option can be changed to the opposite 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 once, and if you change which option, the error disappears, and then looks for the error that should be selected. These options can be selected directly in Project / Settings ..., usually do not modify manually. Since the above analysis is quite comprehensive, this method is most effective. 2. When you have the programming process, you should pay attention to the test Release version, so as not to have too many last code, time is very tight. 3. Use the / W4 warning level in the Debug version, which can get the maximum error message from the compiler, such as if (i = 0), will cause / W4 warning. Don't ignore these warnings, usually this is caused by BUG in your program. But sometimes / W4 will bring a lot of redundant information, such as unused function parameters warning, and many messages handlers ignore certain parameters. We can use: #progma warning (disable: 4702) // // ... #Progma Warning (Default: 4702) // Re-allowed to temporarily disable a warning, or use #Progma Warning (Push, 3) // Set the warning level / w3 // ... #Progma Warning (POP) // Reset to / W4 To temporarily change the warning level, sometimes you can only use the suspicious code to use /w4.4. You can also debug your Release version as Debug, just join the debug symbol. In Project / Settings ..., select Settings for "Win32 Release", select the C / C label, category selection General, Debug Info, select Program Database. Then, in the LINK tag Project Options, finally, "/ OPT: REF" (quotation marks do not lose). This allows the debugger to use the debug symbols in the PDB file. But when you debug, you will find a breakpoint is difficult to set, and the variable is also difficult to find - these are optimized. Fortunately, the Call Stack window is still working properly, even if the frame pointer is optimized, the stack information (especially the return address) can still be found. This is very helpful for positioning errors.