C++ 在调试模式下不存在发​​布版本中的错误的常见原因

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1762088/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:06:38  来源:igfitidea点击:

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

c++release-modedebug-mode

提问by Benny

What are the typical reasons for bugs and abnormal program behavior that manifest themselves only in release compilation mode but which do not occur when in debug mode?

仅在发布编译模式下出现但在调试模式下不出现的错误和异常程序行为的典型原因是什么?

采纳答案by Priyank Bolia

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

很多时候,在 C++ 的调试模式下,所有变量都是空初始化的,而除非明确说明,否则在发布模式下不会发生同样的情况。

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.

还要检查所有异常,例如与发布模式没有直接关系,但有时我们只是忽略一些关键异常,例如 VC++ 中的内存访问冲突,但至少在其他操作系统(如 Linux、Solaris)中同样可能存在问题。理想情况下,您的程序不应捕获诸如访问 NULL 指针之类的关键异常。

回答by Henrik

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

一个常见的陷阱是在 ASSERT 中使用具有副作用的表达式。

回答by stusmith

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.
  • 在垃圾收集语言中,收集器通常在释放模式下更积极;
  • 内存的布局可能经常不同;
  • 内存可能会以不同的方式初始化(​​例如,可以在调试模式下归零,或者在发布时更积极地重新使用);
  • 局部变量可能会被提升为在 release 中注册值,这可能会导致浮点值出现问题。

回答by the_mandrill

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:

过去,我被许多错误所困扰,这些错误在 Debug 版本中很好,但在 Release 版本中会崩溃。有许多根本原因(当然包括本主题中已经总结的那些),并且我已经被以下所有原因所吸引:

  • Member variables or member functions in an #ifdef _DEBUG, so that a class is a different size in a debug build. Sometimes #ifndef NDEBUGis used in a release build
  • Similarly, there's a different #ifdefwhich 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 packthat 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
  • 中的成员变量或成员函数#ifdef _DEBUG,以便类在调试版本中具有不同的大小。有时#ifndef NDEBUG用于发布版本
  • 同样,有一个不同的地方#ifdef恰好只出现在两个版本之一中
  • 调试版本使用系统库的调试版本,尤其是堆和内存分配函数
  • 发布版本中的内联函数
  • 头文件的包含顺序。这不应该引起问题,但是如果您有类似的东西#pragma pack尚未重置,那么这可能会导致令人讨厌的问题。使用预编译头和强制包含也会出现类似问题
  • 缓存:您可能有一些代码,例如仅在发布版本中使用的缓存,或不同的缓存大小限制
  • 项目配置:调试和发布配置可能有不同的构建设置(使用 IDE 时可能会发生这种情况)
  • 由于仅调试代码而发生的竞争条件、计时问题和其他副作用

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.
  • 如果可以,尝试在调试版本中重现异常行为,甚至更好的是,编写一个单元测试来捕获它
  • 想想两者之间的不同之处:编译器设置、缓存、仅调试代码。尝试暂时最小化这些差异
  • 创建关闭优化的发布版本(这样您更有可能在调试器中获得有用的数据)或优化的调试版本。通过最小化调试和发布之间的更改,您更有可能能够隔离导致错误的差异。

回答by Remo.D

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

它可以,特别是如果您在 C 领域。

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.

一个原因可能是 DEBUG 版本可能会添加代码来检查杂散指针并以某种方式保护您的代码免于崩溃(或行为不正确)。如果是这种情况,您应该仔细检查从编译器获得的警告和其他消息。

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!

编辑:我看到其他人提到了它:当然,如果不在调试模式下编译,您可能有整个代码部分有条件地排除。如果是这样,我希望这真的是调试代码,而不是对程序本身的正确性至关重要的东西!

回答by Simeon Pilgrim

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.

是的!,如果您有条件编译,则可能存在计时错误(优化的发布代码节,未优化的调试代码)、内存重用与调试堆。

回答by Alex Budovski

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

CRT 库函数在调试与发布(/MD 与 /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 szDestbetter be nbytes long!

例如,调试版本通常会预填充您传递给指定长度的缓冲区以验证您的声明。示例包括strcpy_s,StringCchCopy等。即使字符串提前终止,您的szDest 也最好是n字节长!

回答by Matthew Scharley

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.

在 .NET 中,即使您不使用条件编译(如 )#if DEBUG,编译器在发布模式下的优化仍然比在调试模式下更加自由,这也可能导致仅发布错误。

回答by Max Galkin

Sure, for example, if you use constructions like

当然,例如,如果您使用类似的结构

#if DEBUG

//some code

#endif

回答by Konamiman

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 DEBUGstatements or via methods marked with the Conditionalattribute.

没有更多细节,我会假设“不正常”意味着它要么不编译,要么在运行时抛出某种错误。检查您是否有依赖编译版本的代码,通过#if DEBUG语句或通过标记有该Conditional属性的方法。