"Turn" Debug is running normally, release version does not run properly

Source: Internet
Author: User

Http://blog.csdn.net/ruifangcui7758/archive/2010/10/18/5948611.aspx
Introduction
If you encounter a common error in your development process, perhaps your release version does not work and the debug version runs correctly, I recommend that you read this article: Because the release version does not, as you might expect, guarantee that your application will run like a debug version. If you have never done release release testing after the development phase has been completed or for a period of time in development, but when you are testing the problem, see our debug Rule 1:
Rule 1:

Regular testing of debug and release versions of development software. The longer the time interval for testing release versions, the more difficult it is to troubleshoot problems, and at least 1 tests per week for release releases, allowing you to save potential troubleshooting time during a tight development cycle. Do not arbitrarily delete the code required for release release This may seem obvious, but it is a mistake that developers inadvertently make, because the compiler compiles release versions to proactively exclude macros that exist in code. For example, assert and trace are automatically excluded from release versions, so the problem is that the code you run in these macros is also deleted, which is a very dangerous thing, J, for example: ASSERT (M_imagelist.create ( Makeintresource (Idb_images), 1, RGB (255,255,255)); Such code will not go wrong in debug mode, the image list is created automatically, but in the release version? Subsequent use of the M_imagelist object only results in the crash! of the program, so the Assert macro uses logical operators as a validation as much as possible.
Rule 2:

Do not place the code where it is executed only in some compilation options, and the code inside of a compilation option macro that uses _DEBUG must not affect the use of the entire program.
Rule 3:

Instead of using rule 2 as a criterion to remove an Assert macro, an Assert macro is a useful tool, but an error is easy to use. Make debug compilation mode close to release mode if the problem with your release version is caused by the code being automatically excluded by the compiler, your problem may be reproduced in this way. Some of the problems may be caused by predefined symbols between different compilation options, so you can change the predefined symbols in the compilation mode so that your debug mode approaches release mode to see if the error is generated, and changes to the compiled predefined notation are as follows: A. ALT-F7 Open Project Settings , on the C++/C page, select the "General" category and change the "_DEBUG" symbol to "ndebug". B. On the C++/C page, select the "Preprocessor" category and add the predefined symbol "_DEBUG" to the "Undefined Symbols" column. C.. Recompile with "Rebuild all" if the problem under Release compilation mode is reproduced in debug mode with the above settings, then you should modify your code according to the following steps: A. Find assert excludes all important execution statements in it. or change the Assert to verify. B: Check all code in "#ifdef _DEBUG" to exclude code used by release mode. C: Look for trace to exclude all of the important execution statements. Trace and assert, compile only in debug mode. If you correct the problem in debug mode with the above modification, then you can recompile the release mode, it is very possible that you can solve the problem previously existed!. Incorrect assumptions cause compilation mode errors Do you regularly assume that your variable or object is being initialized to a specified value (maybe 0)? Do you assume that all of your associated resources exist in the application? These are also the causes of different problems in the debug and release modes.
Rule 4:

You cannot make the above assumptions unless you initialize the variables in your code. Includes global variables, automatic variables, request objects, and new objects. This situation also often occurs in the memory sequence of the problem, remember the original use of the structure of the time for ease of use, compare two structural objects using MEMCMP, the debug version is working properly, and release version calculated the wrong solution, it does not seem to make the wrong assumption!
Rule 5:

Make sure that all references to the deleted resource are deleted, such as the definition in resource.h. In software development, different compiled versions have different initialization of variables and memory. If you assume that the variable is initialized to 0, an exception occurs in the release mode of the Win9x system. Therefore, it is safer to explicitly clear 0 memory for all variables. If you refer to a resource that has been deleted, your debug version works, but the release version may be crash. Do you believe in compilers? Compiler warning levels and compilation noise have a significant relationship. By increasing the compiler warning level, you can increase the chance that the program hides the problem from being exposed. Usually set warning levels at "Level 3" or "4". Compile and resolve all warnings, This is a good recommendation for releasing the release release application. This exposes many initialization issues and other potential errors that can cause problems in your application.
Rule 6:

Before starting the project, set the build warning level to "levels 3" or "4" to ensure that all warnings are eliminated before registering the code!. Summary report debug in compile mode once more than once heard some VC developers said release mode can not be debugged, Rule 7:

When all methods in the current polygon are invalid, debug under Release mode. Release mode can be debugged, the first step is to open the symbol table: A. Alt-f7 open the project settings, on the C++/C page, select the "General" class, modify the debug Info setting to "program Database". B: On the "Link" page, select "Generate Debug Info". C: "Rebuild All" These settings will allow you to keep the symbol table in release mode, and you can also consider the following settings: A. Debug release version of the application, you can turn off optimization options. B. If a breakpoint cannot be set under Release mode, adding the instruction "__asm {int 3}" can cause your application to stop at that line (to be sure to exclude the code when the application is published). There are several limitations to debugging in release mode. A. B.. Ditto, to debug the called DLLs, you must add debug information and symbol tables to them all. The compiler generated the wrong code? Perhaps sometimes you will find VC + + compiler generated a ' problem code ',. If this action solves your problem,. For example, the following code appears to be all ' normal ' in the debug mode, but it will go wrong under release mode!

#include int* func1 ()

{

int retval = 5;

Return &retval;

}

int main (int argc, char* argv[])

{

printf ("%d\n", *func1 ());

return 0;

}

I believe most programmers, especially beginners, are prone to this kind of situation.
Rule 8:


Rule 9:

If you have thoroughly checked your code and have not found a problem, you might want to turn on the optimization option one by another to limit the cause of the error to a certain range. btw-The above problem code is automatically checked out by the C + + compiler. If you have followed rule 6, you may have addressed these issues in the previous session. With my development experience, the compiler rarely produces the wrong code (and, of course, the interface program boundary alignment problem). Typically, when using a template class, the VC6 compiler might generate an assert assert error, which you can fix only by updating the patch.
The final thinking in the daily coding only a little bit more stringent detection, it can effectively avoid the new debug-v-release mode problem generation, the following are some of my experience.
1. Remove (check out) the code that needs to be modified.
2. Modify the code, exclude all warnings, compile debug and release versions.
3. Test the new code in detail, i.e. enter the work code after stepping through the new code snippet to ensure that the code is correct.
4. Correct all issues.
5. Register the new code in the library (check in) after the error is confirmed.
6. Complete a new compilation of the registered code to ensure that the new registration code is fused with other code.
7. Re-test the code in detail.
8. Correct the new problem (perhaps you can find the problem of registering the inbound code) in strict accordance with the above steps, you can solve a large number of problems during the design and development process, to avoid creating new and difficult to locate problems in the final release of the application. PostScript This article is in my development process encountered release version of the application release, the error when the hard quest to get some of the experience, the original source from, after I polish, rewrite to become suitable for domestic developers of the article, hope to be useful to everyone, thank you! Reprint: The debug version includes debug information, so it is much larger than the release version (may be hundreds of K to several m large). As for whether DLL support is required, it depends on the compilation options you use. In the case of ATL-based, the debug and release versions have the same requirements for DLLs. If you are using an MFC dynamic library with the compile option, you need library support such as MFC42D.DLL, and the release version requires MFC42.DLL support. Release build does not debug the source code, regardless of MFC's diagnostic macros, using the MFC release library, compiled 10 for the speed of the application optimization, and debug build is the reverse, it allows the source code debugging, you can define and use the MFC diagnostic macros, Using the MFC debug Library, the speed is not optimized.
The essential difference between Debug and Release compilation methods debug is often called a debug version, it contains debug information, and does not make any optimizations to facilitate the programmer to debug the program. Release, known as the release version, is often optimized to make the program optimal in terms of code size and speed, so users can use it well. The real secret of Debug and Release lies in a set of compilation options. The options for both are listed below (and of course there are others, such as/FD/FO, but the difference is not important and usually they do not cause the release version error, not discussed here) Debug version:/mdd/mld or/MTD using debug runtime Libr ARY (Debug version runtime function library)/od off optimization switch/d "_DEBUG" equivalent to #define _DEBUG, open compile debug code switch (mainly for assert function)/zi create Edit and Continue (edit continue) database, so If you modify the source code during debugging, you do not need to recompile/gz to help capture memory errors/gm Open the Minimize relink switch, reduce link time release version:/MD/ML or/MT Use the release version of the runtime function library/o1 or/o2 optimization switch to make the program the smallest or most Fast/D "Ndebug" Close conditional compilation debug code switch (that is, do not compile assert function)/GF merge duplicate strings and put string constants into read-only memory to prevent modification in fact, Debug and Release have no intrinsic boundaries, they are just a set of compilation options, The compiler simply acts according to the intended options. In fact, we can even modify these options to get an optimized debug version or a release version with a trace statement.
Second, in which case release version will be wrong with the above, let's look at each of these options to see how the release version of the error is generated 1. Runtime Library: Linking which runtime libraries usually affect only the performance of the program. The debug version of the Runtime Library contains debugging information and uses some protection mechanisms to help identify errors, so performance is not as good as the release version. The runtime library provided by the compiler is usually stable and does not cause release errors, but the Debug runtime library strengthens the detection of errors, such as heap memory allocations, sometimes with debug error but Release normal. It should be pointed out that if the Debug error, even if the release is normal, the program must be a Bug, but it is possible that the release version of a run did not show it. 2. Optimizations: This is the main cause of the error, because the source program is basically translated directly when the optimization is turned off, and the compiler makes a series of assumptions when the optimization is turned on. There are several main types of errors:
(1) Frame pointer (frame Pointer) ellipsis (FPO): All invocation information (return address, parameters) and automatic variables are placed in the stack during a function call. If the Declaration and implementation of the function is different (parameter, return value, call method), it will produce error ―――― but in the Debug mode, the access of the stack is implemented by the address saved by the EBP register, and if there are no errors (or "not many") in the array, the function will normally execute normally; Release mode, optimizations omit the EBP stack base pointer, so accessing the stack via a global pointer can cause the return address error to be a program crash. The strong-type nature of C + + can check for most of these errors, but it will not work if a forced type conversion is used. You can force the/oy-compilation option in the release version to turn off the frame pointer ellipsis to determine if such an error occurred. This type of error usually has the following: MFC message response function writing error. The correct should be afx_msg LRESULT Onmessageown (WPARAM WPARAM, LPARAM LPARAM); The On_message macro contains coercion type conversions. One way to prevent this error is to redefine the On_message macro, add the following code to StdAfx.h (after the # include "AFXWIN.h"), the compiler will error when the function is wrong #undef on_message #define On_ Message (message, MEMBERFXN) \ {message, 0, 0, 0, AFXSIG_LWL, \ (afx_pmsg) (AFX_PMSGW) (static_cast< LRESULT (afx_msg_cal L \ 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). Optimizer to improve program performance, some variables are often placed in registers (similar to the Register keyword), while other processes can only modify the memory in which the variable resides, while the value in the register does not change. If your program is multithreaded, or if you find that the value of a variable does not match your expectations and you are sure that the settings are correct, you are likely to encounter such a problem. This error sometimes manifests itself as a program with the fastest optimization error and minimal optimization. Try adding volatile variables that you think are suspicious.
(3) Variable optimization: The optimizer optimizes variables based on the use of variables. For example, there is an unused variable in the function, and in the Debug version it is possible to mask an array out of bounds, while in release the variable is likely to be tuned, when the array is out of bounds destroying the useful data in the stack. Of course, the actual situation will be much more complicated than this. The errors associated with this are: illegal access, including array out of 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 variable a[4] = 1; Although the scope of the array is out of bounds, the space is not retracted, so I and J will cover the bounds. The release version because I, J does not have a large role may be optimized, so that the stack is destroyed. 3. _DEBUG and Ndebug: When _DEBUG is defined, the Assert () function is compiled, and Ndebug is not compiled. In addition, VC + + also has a series of assertion macros. This includes: ANSI C asserts void assert (int expression); C Runtime Lib asserts _assert (booleanexpression); _asserte (booleanexpression); MFC asserts assert (booleanexpression); VERIFY (booleanexpression); Assert_valid (Pobject); Assert_kindof (classname, pobject); ATL asserts Atlassert (booleanexpression); In addition, the compilation of TRACE () macros is also controlled by _DEBUG. All of these assertions are compiled only in the debug version and are ignored in the release version. The only exception is VERIFY (). In fact, these macros all call the Assert () function, except that they attach some debug code related to the library. If you add any program code to these macros, not just Boolean expressions (such as assignments, function calls that change the value of the variables, etc.), the release version does not perform these operations, causing errors. It's easy for beginners to make such mistakes, and the way to find them is simple, as these macros are listed above as long as they are found using VC + + 's Find in Files feature in all project files.The place to check again. In addition, some experts may also join #ifdef _DEBUG such as conditional compilation, but also pay attention to. Incidentally, it is worth mentioning that the VERIFY () macro, which allows you to put the program code in a Boolean expression. This macro is typically 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 assertions, does not completely separate the program code from the debug code, and can eventually cause a lot of trouble. Therefore, experts recommend using this macro as sparingly as possible. 4./GZ option: This option will do the following (1) initialize memory and variables. Including initializing all automatic variables with 0xCC, 0xCD (cleared data) initializes the allocated memory in the heap (i.e. dynamically allocated memory, such as New), 0xDD (Dead Data) fills the heap memory that has been freed (for example, delete), 0xFD (Defe NCDE Data) initializes protected memory (the debug version adds protection memory to prevent cross-border access before and after dynamically allocating memory), where the words in parentheses are the mnemonic words suggested by Microsoft. The advantage of this is that these values are large, and as pointers are not possible (and the pointers in the 32-bit system are rarely odd, and in some systems odd pointers produce run-time errors), are rarely encountered as numeric values, and they are easily recognizable, so this is useful for finding release in Debug version Version of the error that you will encounter. It is important to note that many people think that the compiler will initialize the variable with the ".", which is wrong (and this is very bad for finding errors). (2) When a function is called through a function pointer, the matching of the function call is verified by checking the stack pointer. (Prevent prototype mismatch) (3) Check the stack pointer before the function returns, confirming that it has not been modified. (Prevent cross-border access and prototype mismatch, with the second item can be roughly simulated frame pointer omitted FPO) generally/gz option will cause Debug version error and release version normal phenomenon, because the release version of the uninitialized variable is random, it is possible to point the pointer to a valid address and mask The illegal access. In addition, options such as/GM/GF are less likely to cause errors, and their effects are obvious and easier to spot.

In the process of using VC development software, just to enjoy the excitement of the time suddenly found: Release and debug run inconsistent results, and even error, and release is not easy to debug, really is blow ah, but pain return pain, the problem always to solve, the following will tell me about my two points of experience, See if it is one of them:

1. Variables. As you know, Debug and release do different things when initializing variables, debug is to assign each byte bit to 0XCC, and the assignment of release is approximate to random (I want to be allocated directly from memory, not initialized, But why debug is not 0xff or 0x00 or anything else is unclear. This makes it clear that if a variable in your program is referenced without being initialized, there is a good chance of an exception: the use of a control variable will result in a process-oriented inconsistency, and being used as an array subscript will cause the program to crash, and more likely to cause inaccuracies in other variables to cause other errors. Therefore, it is the simplest and most effective way to initialize a default value immediately after declaring a variable, otherwise you will find no place to find it. Code errors in the debug mode may be ignored without being detected, such as the debug mode of the array out of bounds also most can not error, in the release is exposed, this find is more difficult: ( You should pay attention to it yourself. 2. The message parameters for the custom message. MFC has provided us with a good message mechanism, but also added a custom message, the benefits I will not have to say more. Is there a problem with Debug and release? The answer is yes. When you declare a function body of a custom message, you will often see such a notation: afx_msg LRESULT onmessageown (); Errors such as invalid handles are caused when you use message passing between threads or processes. The reason is that the message body parameters are not added, that should be written: afx_msg LRESULT onmessageown (WPARAM WPARAM, LPARAM LPARAM); (For specific reasons, I'm not sure, is it because the default parameters are called to allocate more wparam+lparam space and destroy the memory space of the application?)

Methods to avoid:

1. Notice the initialization of the variable

2. Standard notation for custom messages

3. Use debug statement trace and so on after use, it is best to comment out

4. Try to use Try-catch (...)

The difference between VERIFY and ASSERT: One can be executed under release, one cannot be

Debug and release version differences and debugging related issues: memory allocation issue 1. The variable is not initialized. The following program runs very well in debug.

Thing * Search (thing * something)

BOOL found;

for (int i = 0; i < whatever. GetSize (); i++)

{

if (Whatever[i]->field = = Something->field)

{/* found it */found = TRUE; break;}

/* Found it */

}

if (found)

return whatever[i];

Else

return NULL;

But not in release, because in debug, the variable is automatically initialized to Found=false, and in the release version will not. So initialize the variable, class, or struct as much as possible.

2. Data overflow issues such as: Char buffer[10]; int counter; lstrcpy (buffer, "Abcdefghik"), and Null in the debug version overwrites the high of counter, But unless counter>16m, there is nothing wrong. However, in release version, counter may be placed in the register, so that null overwrites the space under buffer, possibly the return address of the function, which causes access ERROR.

3. The mode of memory allocation for debug and release editions is different. If you are applying ele to 6*sizeof (DWORD) =24bytes in the debug version, you are actually assigned 32bytes (the debug version is allocated in 32bytes), and in the release version, Assigned to you is 24bytes (release version in 8bytes units), so in the debug version if you write Ele[6], there may be no problem, and in release version, there is access violate. II. Assert and verify 1. Assert is not compiled in release version. The Assert macro is defined #ifdef _DEBUG #define ASSERT (x) if ((x) = = 0) report_assert_failure () #else #define ASSERT (x) #endif is actually more complex , but it doesn't matter. If you add the code that must be in the program such as ASSERT (pnewobj = new CMyClass) in these statements; Pnewobj->myfunction (); This time the release version of the pnewobj will not be allocated to the space so the execution of the next statement when the program will report that the program has performed an illegal operation error. This can be used VERIFY: #ifdef _DEBUG #define VERIFY (x) if ((x) = = 0) report_assert_failure () #else #define VERIFY (x) (x) #endif such , the code can be executed in the release version. Iii. parameter problem: The processing function of the custom message must be defined as follows: afx_msg LRESULT onmymessage (WPARAM, LPARAM); The return value must be an HRESULT, or debug will be over, and release error IV. Memory allocation guarantees consistency in data creation and cleanup: If a DLL provides a function to create data, the DLL should also provide a function to destroy the data. The creation and cleanup of data should be on the same level. V. DLL disaster people will mix different versions of DLLs caused by the inconsistency image called "Dynamic Connection Library Hell" (DLL Hell), even Microsoft itself said (Http://msdn.microsoft.com/library/techart/dlldanger1.htm). If your program uses your own DLL please note: 1. You cannot mix debug and release versions of DLLs together. Debug is the debug version, release version is release version. The solution is to place the debug and release programs in the Debug and release directories of the main program 2. Never think that static connection libraries will solve the problem, which will only make the situation worse. Vi. Debug in Release board: 1. Change assert () to VERIFY (). Find the code that is defined in "#ifdef _DEBUG", and if you need it in the release version, move them out of the definition. Find Trace (...) Code, because the code is not compiled in release. Please check carefully if the code you need in release is not cheap. 2. There are differences in the initialization of variables, in different systems, or between debug/release versions, so initialize the variables. 3. Do you already have a warning at compile time? Set the warning level to 3 or 4, and then ensure that no warnings appear at compile time. VII. Change the optimization option under Project Settings "C++/C" to Disbale (Debug). Compiler optimizations can cause many unexpected errors, please refer to http://www.pgh.net/~newcomer/debug_release.htm 1. In addition to the release version of the software is also available for debugging, please make the following changes: in the "Project Settings the "c++/c" Item under "category" is "General" and "Debug Info" is set to "program Database". Under the Link item, select the Generate Debug Info check box. The "Rebuild all" approach creates some limitations: You cannot get the value of a variable in an MFC DLL. All DLL works that are used by the software must be modified. Another: MS Bug:ms's technical documentation shows that the "Maximize speed" optimization option for DLLs in VC5 is not fully supported, so this will cause memory errors and cause the program to crash.

"Turn" Debug is running normally, release version does not run properly

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.