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

Ben*_*nny 65 c++ release-mode debug-mode

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

Pri*_*lia 31

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

检查是否有任何调试宏和未初始化的变量

您的程序是否使用线程,然后优化也会在发布模式下导致一些问题.

还要检查所有异常,例如与发布模式没有直接关系,但有时我们会忽略一些关键异常,例如VC++中的mem访问冲突,但至少在Linux,Solaris等其他操作系统中也是如此.理想情况下,您的程序不应该捕获诸如访问NULL指针之类的关键异常.

  • 一个小点:通常,调试模式中的变量不是用空填充,而是在自然界中很少发生某些特定值(例如,对于MSVC为0xCCCCCCCC). (5认同)
  • 我总是发现这种行为完全倒退.当然,调试模式的工作是*暴露*问题,而不是隐藏它们? (4认同)
  • 是的,你是对的,扩展你的答案:http://priyank.co.in/uninitialized-memory-values-in-debug-mode-vc-denotes (2认同)

Hen*_*rik 19

一个常见的陷阱是在ASSERT中使用带副作用的表达式.


stu*_*ith 9

其他差异可能是:

  • 在垃圾收集语言中,收集器通常在发布模式下更具攻击性;
  • 记忆的布局可能经常不同;
  • 内存可以以不同方式初始化(​​例如,可以在调试模式下归零,或者在发布时更积极地重用);
  • 可以将本地提升为在发布中注册值,这可能会导致浮点值出现问题.

  • "在垃圾收集语言中,收集器通常在发布模式下更具攻击性"这听起来相当荒谬.对象是可访问的还是不可访问的.如果gc删除了一个可到达的对象,那就完全错了,如果它没有删除一个不应该导致错误的不可达 - 那么无论如何都无法访问该对象. (2认同)
  • @idmean一点都不荒谬。创建调试二进制文件的唯一目的是中断执行,查看所有作用域内的变量以及维护代码以实现二进制对称。创建发布是为了提高速度和/或最小尺寸。如果知道不需要它们,可以忽略整个函数调用或变量定义。这将创建一个非常不同的内存空间。 (2认同)

the*_*ill 7

我曾经被一些错误所困扰,这些错误在Debug版本中很好但在Release版本中崩溃了.有许多根本原因(当然包括那些已经在这个帖子中总结过的原因)并且我已经被以下所有因素所困扰:

  • 成员变量或成员函数#ifdef _DEBUG,因此在调试版本中类是不同的大小.有时#ifndef NDEBUG用于发布版本
  • 类似地,有一个不同的#ifdef恰好只存在于两个构建中的一个中
  • 调试版本使用系统库的调试版本,尤其是堆和内存分配函数
  • 发布版本中的内联函数
  • 包含头文件的顺序.这不应该导致问题,但如果你有一些#pragma pack没有被重置的东西,那么这可能会导致令人讨厌的问题.使用预编译头和强制包含也可能发生类似问题
  • 缓存:您可能拥有仅在发布版本中使用的缓存等代码,或者不同的缓存大小限制
  • 项目配置:调试和发布配置可能具有不同的构建设置(使用IDE时可能会发生这种情况)
  • 由于仅调试代码而导致的竞争条件,计时问题和错误的副作用

多年来我为积累调试/发布错误而积累的一些技巧:

  • 尝试在调试版本中重现异常行为,如果可以,甚至更好,编写单元测试来捕获它
  • 想想两者之间的区别:编译器设置,高速缓存,仅调试代码.尽量暂时减少这些差异
  • 在关闭优化的情况下创建发布版本(因此您更有可能在调试器中获得有用的数据)或优化的调试版本.通过最小化调试和发布之间的更改,您更有可能隔离导致该错误的差异.