只在发布编译模式下出现但在调试模式下不会出现的 bug 和异常程序行为的典型原因是什么?
你需要提供更多的信息,但是,是的,这是可能的。这取决于调试版本的作用。您可能会有日志记录或额外的检查,这些记录不会被编译成发布版本。这些仅用于调试的代码路径可能具有意想不到的副作用,这些副作用会以奇怪的方式改变状态或影响变量。调试版本通常运行得更慢,因此这可能会影响线程化和隐藏竞态条件。对于直接从发行版编译器进行优化也是一样,发行版编译器有可能(尽管现在不太可能)使优化短路。
当然,例如,如果您使用
#if DEBUG //some code #endif
很多时候,在 C + + 的调试模式下,所有变量都初始化为 null,而在发布模式下,除非明确说明,否则不会发生同样的情况。
检查所有调试宏和未初始化的变量
您的程序是否使用线程,那么优化也可能导致发布模式中的一些问题。
还要检查所有的异常,例如与发布模式没有直接关系的异常,但是有时我们会忽略一些关键的异常,比如 VC + + 中的 mem 访问冲突,但是同样的问题至少在其他操作系统如 Linux、 Solaris 中会出现。理想情况下,您的程序不应该捕获这样的关键异常,如访问 NULL 指针。
如果没有更多的细节,我将假设“ not OK”意味着它要么不编译,要么在运行时抛出某种错误。检查是否有依赖于编译版本的代码,可以通过 #if DEBUG语句,也可以通过标记为 Conditional属性的方法。
#if DEBUG
Conditional
太棒了!,如果您有条件编译,可能存在计时错误(优化的发布代码,非优化的调试代码) ,内存重用与调试堆。
进去。NET,即使你不使用像 #if DEBUG这样的条件编译,编译器在发布模式下的优化仍然比在调试模式下更加自由,这也会导致只发布 bug。
其他不同之处可能包括:
一个常见的缺陷是在 ASSERT 中使用具有副作用的表达式。
它可以,特别是如果你在 C 领域。
其中一个原因可能是 DEBUG 版本可能会添加代码来检查偏离的指针,并以某种方式保护您的代码免于崩溃(或行为不正确)。如果是这种情况,您应该仔细检查从编译器获得的警告和其他消息。
另一个原因可能是优化(对于发布版本,优化通常是开启的,对于调试,优化是关闭的)。代码和数据布局可能已经进行了优化,而当您的调试程序只是,例如,访问未使用的内存时,发布版本现在正试图访问保留内存,甚至指向代码!
编辑: 我看到其他人提到它: 当然,如果不在 DEBUG 模式下编译,您可能会有整个代码段被有条件地排除在外。如果是这样的话,我希望这是真正的调试代码,而不是对程序本身的正确性至关重要的东西!
有可能。如果发生这种情况,并且不涉及条件编译,那么您可以非常确定您的程序是错误的,并且仅仅由于偶然的内存初始化或内存中的布局而在调试模式下工作!
可以破解有效代码有编译器优化,因为它们太主动了。
尝试在打开较少优化的情况下编译代码。
这是可能的,如果您有条件编译,以便调试代码和发布代码是不同的,并且代码中有一个只在发布模式中使用的 bug。
除此之外,不可能。调试代码和发布代码的编译方式存在差异,在调试器下运行与否的代码执行方式也存在差异,但如果这些差异导致除性能差异以外的任何其他原因,问题就一直存在。
在调试版本中,错误可能不会发生(因为计时或内存分配是不同的) ,但这并不意味着错误不存在。也许还有其他与调试模式无关的因素会改变代码的计时,从而导致错误发生或不发生,但归根结底,如果代码是正确的,那么在任何情况下都不会发生错误。
所以,不,调试版本是不正确的,因为您可以运行它而不会得到一个错误。如果在发布模式下运行时发生错误,那不是因为发布模式,而是因为错误从一开始就存在。
CRT 库函数在调试和发布(/MD vs/MDd)中的行为是不同的。
例如,调试版本通常预先填充传递到指定长度的缓冲区,以验证声明。例如 strcpy_s、 StringCchCopy等。即使字符串提前终止,您的 SzDest最好是 N字节长!
strcpy_s
StringCchCopy
我曾经被一些 bug 所困扰,这些 bug 在 Debug 构建中很好,但在发布构建中崩溃了。有许多潜在的原因(当然包括那些已经在这个帖子中总结出来的原因) ,我被以下所有的原因所困扰:
#ifdef _DEBUG
#ifndef NDEBUG
#ifdef
#pragma pack
这些年来,我积累了一些深入探究调试/发布 bug 的技巧:
在非 void 函数中,所有执行路径都应以 return 语句结束。
在调试模式下,如果您忘记以 return 语句结束这样的路径,那么函数通常默认返回0。
但是,在发布模式下,函数可能会返回垃圾值,这可能会影响程序的运行方式。
我只是在调用程序集函数时遇到了这种情况,该函数没有还原寄存器以前的值。
在“发布”配置中,VS 使用/O2进行编译,从而优化了代码的速度。因此,一些局部变量仅仅映射到与上述函数共享的 CPU 寄存器(用于优化) ,就会导致严重的内存损坏。
不管怎样,看看在代码中的任何地方是否间接地扰乱了 CPU 寄存器。
我记得以前我们在 c/c + + 中构建 dll 和 pdb 的时候。
我记得这个:
然后继续这个循环。
我们有时会暂时将发布版本替换为 dll 的调试版本,以便在处理这些 bug 时不会延迟生产。
另一个原因可能是 DB 调用。 是否在同一线程中多次保存和更新同一记录, 有时是为了更新。 更新可能失败或者不能按预期工作,因为前面的 create 命令仍在处理中,对于更新,db 调用未能找到任何记录。 这在调试中不会发生,因为调试器确保在着陆前完成所有挂起的任务。