开发者

Common reasons for bugs in release version not present in debug mode

What are the typical reasons for bugs and abnormal program behavior that 开发者_如何学JAVAmanifest themselves only in release compilation mode but which do not occur when in debug mode?


Many times, in debug mode in C++ all variables are null initialized, whereas the same does not happen in release mode unless explicitly stated.

Check for any debug macros and uninitialized variables

Does your program uses threading, then optimization can also cause some issues in release mode.

Also check for all exceptions, for example not directly related to release mode but sometime we just ignore some critical exceptions, like mem access violation in VC++, but the same can be a issue at least in other OS like Linux, Solaris. Ideally your program should not catch such critical exceptions like accessing a NULL pointer.


A common pitfall is using an expression with side effect inside an ASSERT.


I've been bitten by a number of bugs in the past that have been fine in Debug builds but crash in Release builds. There are many underlying causes (including of course those that have already been summarised in this thread) and I've been caught out by all of the following:

  • Member variables or member functions in an #ifdef _DEBUG, so that a class is a different size in a debug build. Sometimes #ifndef NDEBUG is used in a release build
  • Similarly, there's a different #ifdef which happens to be only present in one of the two builds
  • The debug version uses debug versions of the system libraries, especially the heap and memory allocation functions
  • Inlined functions in a release build
  • Order of inclusion of header files. This shouldn't cause problems, but if you have something like a #pragma pack that hasn't been reset then this can lead to nasty problems. Similar problems can also occur using precompiled headers and forced includes
  • Caches: you may have code such as caches that only gets used in release builds, or cache size limits that are different
  • Project configurations: the debug and release configurations may have different build settings (this is likely to happen when using an IDE)
  • Race conditions, timing issues and miscellanous side-effects occurring as a result of debug only code

Some tips that I've accumulated over the years for getting to the bottom of debug/release bugs:

  • Try to reproduce anomalous behaviour in a debug build if you can, and even better, write a unit test to capture it
  • Think about what differs between the two: compiler settings, caches, debug-only code. Try to minimise those differences temporarily
  • Create a release build with optimisations switched off (so you're more likely to get useful data in the debugger), or an optimised debug build. By minimising the changes between debug and release, you're more likely to be able to isolate which difference is causing the bug.


Other differences might be:

  • In a garbage-collected language, the collector is usually more aggressive in release mode;
  • Layout of memory may often be different;
  • Memory may be initialized differently (eg could be zeroed in debug mode, or re-used more aggressively in release);
  • Locals may be promoted to register values in release, which can cause issues with floating point values.


Yes!, if you have conditional compilation, there may be timing bugs (optimised release code verse, non-optimised debug code), memory re-use vs. debug heap.


It can, especially if you are in the C realm.

One cause could be that the DEBUG version may add code to check for stray pointers and somehow protect your code from crashing (or behave incorrectly). If this is the case you should carefully check warnings and other messages you get from your compiler.

Another cause could be optimization (which is normally on for release versions and off for debug). The code and data layout may have been optimized and while your debugging program just was, for example, accessing unused memory, the release version is now trying to access reserved memory or even pointing to code!

EDIT: I see other mentioned it: of course you might have entire code sections that are conditionally excluded if not compiling in DEBUG mode. If that's the case, I hope that is really debugging code and not something vital for the correctness of the program itself!


The CRT library functions behave differently in debug vs release (/MD vs /MDd).

For example, the debug versions often prefill buffers you pass to the indicated length to verify your claim. Examples include strcpy_s, StringCchCopy, etc. Even if the strings terminate earlier, your szDest better be n bytes long!


Sure, for example, if you use constructions like

#if DEBUG

//some code

#endif


You'd need to give a lot more information, but yes, it's possible. It depends what your debug version does. You may well have logging or extra checks in that that don't get compiled into a release version. These debug only code paths may have unintended side effects which change state or affect variables in strange ways. Debug builds usually run slower, so this may affect threading and hide race conditions. The same for straight forward optimisations from a release compile, it's possible (although unlikely these days) that a release compile may short circuit something as an optimisation.


Without more details, I will assume that "not OK" means that it either does not compile or throws some sort of error at runtime. Check if you have code that relies on the compilation version, either via #if DEBUG statements or via methods marked with the Conditional attribute.


In .NET, even if you don't use conditional compilation like #if DEBUG, the compiler is still alot more liberal with optimisations in release mode than it is in debug mode, which can lead to release only bugs as well.


That is possible, if you have conditional compilation so that the debug code and release code are different, and there is a bug in the code that is only use in the release mode.

Other than that, it's not possible. There are difference in how debug code and release code are compiled, and differences in how code is executed if run under a debugger or not, but if any of those differences cause anything other than a performance difference, the problem was there all along.

In the debug version the error might not be occuring (because the timing or memory allocation is different), but that doesn't mean that the error is not there. There may also be other factors that are not related to the debug mode that changes the timing of the code, causing the error to occur or not, but it all boils down to the fact that if the code was correct, the error would not occur in any of the situations.

So, no, the debug version is not OK just because you can run it without getting an error. If an error occurs when you run it in release mode, it's not because of the release mode, it's because the error was there from the start.


There are compiler optimizations that can break valid code because they are too aggressive.

Try compiling your code with less optimization turned on.


In a non-void function, all execution paths should end with a return statement.

In debug mode, if you forget to end such a path with a return statement then the function usually returns 0 by default.

However, in release mode your function may return garbage values, which may affect how your program runs.


It's possible. If it happens and no conditional compilation is involved, than you can be pretty sure that your program is wrong, and is working in debug mode only because of fortuitous memory initializations or even layout in memory!


I just experienced that when I was calling an assembly function that didn't restored the registers' previous values.

In the "Release" configuration, VS was compiling with /O2 which optimizes the code for speed. Thus some local variables where merely mapping to CPU registers (for optimization) which were shared with the aforementioned function leading to serious memory corruption.

Anyhow see if you aren't indirectly messing with CPU registers anywhere in your code.


Another reasons could be DB calls. Are you saving and updating same record multiple times in same thread, sometimes for updating. Its possible the update failed or didnt work as expected because the previous create command was still processing and for update, the db call failed to find any record. this wont happen in debug as debugger makes sure to complete all pending tasks before landing.


I remember while ago when we were building dll and pdb in c/c++.

I remember this:

  • Adding log data would sometime make the bug move or disappear or make a totally other error appears (so it was not really an option).
  • Many of these errors where related to char allocation in strcpy and strcat and arrays of char[] etc...
  • We weeded some out by running bounds checker and simply fixing the memory alloc/dealloc issues.
  • Many times, we systematically went through the code and fixed a char allocation.
  • My two cents is that it is related to memory allocation and management and constraints and differences between Debug mode and release mode.

And then kept at going through that cycle.

We sometimes, temporarily swapped release for debug versions of dlls, in order not to hold off production, while working on these bugs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜