代码之家  ›  专栏  ›  技术社区  ›  marc.d

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

  •  59
  • marc.d  · 技术社区  · 7 年前

    18 回复  |  直到 16 年前
        1
  •  34
  •   Priyank Bolia    16 年前

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

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

        2
  •  21
  •   Henrik    16 年前

    一个常见的陷阱是在断言中使用带有副作用的表达式。

        3
  •  11
  •   the_mandrill    16 年前

    在过去,我一直被一些bug所困扰,这些bug在调试版本中表现良好,但在发布版本中崩溃。有许多潜在的原因(当然包括那些已经在这篇文章中总结过的原因),我已经被以下所有的原因抓住了:

    • 中的成员变量或成员函数 #ifdef _DEBUG ,以便类在调试生成中具有不同的大小。有时 #ifndef NDEBUG
    • 同样,也有不同的方法 #ifdef 这恰好只出现在两个版本中的一个版本中
    • 调试版本使用系统库的调试版本,特别是堆和内存分配函数
    • 发布版本中的内联函数
    • 头文件的包含顺序。这不会引起问题,但是如果你有 #pragma pack
    • 缓存:您可能有一些代码,比如只在发布版本中使用的缓存,或者不同的缓存大小限制
    • 仅调试代码导致的竞争条件、计时问题和其他副作用

    • 想想这两者之间的区别:编译器设置、缓存、仅调试代码。暂时尽量减少这些差异
    • 在关闭优化的情况下创建发布版本(这样您更有可能在调试器中获得有用的数据),或者创建优化的调试版本。通过最小化调试和发布之间的更改,您更有可能隔离导致错误的差异。
        4
  •  9
  •   stusmith    16 年前

    • 在垃圾收集语言中 在释放模式下;
    • 内存的布局可能会改变 经常是不同的;
    • 记忆可能是 初始化方式不同(如可以 在调试模式下归零,或重复使用更多
    • 被提升为在发布中注册值,可以
        5
  •  3
  •   Simeon Pilgrim    16 年前

    对如果您有条件编译,则可能存在计时错误(优化的发行版代码、非优化的调试代码)、内存重用与调试堆。

        6
  •  3
  •   Remo.D    16 年前

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

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

        7
  •  3
  •   Alex Budovski    16 年前

    CRT库函数在调试与发布(/MD vs/MDd)中的行为不同。

    strcpy_s , StringCchCopy ,等等。即使字符串提前终止,您的 szDest 最好是 字节长!

        8
  •  2
  •   Massimiliano    16 年前

    当然,例如,如果您使用如下结构

    #if DEBUG
    
    //some code
    
    #endif
    
        9
  •  1
  •   blowdart    16 年前

    你需要提供更多的信息,但是是的,这是可能的。这取决于调试版本的功能。您可能会有日志记录或额外的检查,但这些检查不会被编译到发布版本中。这些只进行调试的代码路径可能会产生意外的副作用,这些副作用会以奇怪的方式更改状态或影响变量。调试生成通常运行较慢,因此这可能会影响线程和隐藏竞争条件。对于发布编译的直接优化也是如此,发布编译有可能(尽管现在不太可能)使优化短路。

        10
  •  1
  •   Konamiman    16 年前

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

        11
  •  1
  •   Matthew Scharley    16 年前

    #if DEBUG ,编译器在发布模式下的优化比在调试模式下的要自由得多,这也可能导致只发布错误。

        12
  •  1
  •   Guffa    16 年前

    这是可能的,如果您有条件编译,使得调试代码和发布代码不同,并且代码中存在一个只在发布模式下使用的bug。

    除此之外,这是不可能的。调试代码和发布代码的编译方式不同,在是否在调试器下运行的情况下,代码的执行方式也不同,但如果这些差异中的任何一个导致性能差异以外的任何差异,那么问题始终存在。

    在调试版本中,错误可能没有发生(因为时间或内存分配不同),但这并不意味着错误不存在。可能还有其他与调试模式无关的因素,这些因素会改变代码的计时,从而导致错误是否发生,但归根结底,如果代码是正确的,那么在任何情况下都不会发生错误。

        13
  •  1
  •   Georg Schölly Crazy Developer    16 年前

    有一些编译器优化 因为他们太咄咄逼人了。

        14
  •  1
  •   loudandclear    13 年前

    在调试模式下,如果您忘记用return语句结束这样的路径,那么默认情况下该函数通常返回0。

    但是,在释放模式下,函数可能返回垃圾值,这可能会影响程序的运行方式。

        15
  •  0
  •   UncleZeiv    16 年前

    这是可能的。如果发生这种情况,并且不涉及条件编译,那么您可以非常确定您的程序是错误的,并且仅由于偶然的内存初始化,甚至内存中的布局而在调试模式下工作!

        16
  •  0
  •   mycelo    11 年前

    我只是在调用没有恢复寄存器先前值的汇编函数时体验到了这一点。

    无论如何,看看你是否在代码中的任何地方间接地弄乱了CPU寄存器。

        17
  •  0
  •   Pratyush Dhanuka    7 年前

    另一个原因可能是DB调用。 是否在同一线程中多次保存和更新同一记录, 有时需要更新。 更新可能失败或未按预期工作,因为上一个create命令仍在处理,对于更新,db调用未能找到任何记录。 这在调试中不会发生,因为调试器确保在登录之前完成所有挂起的任务。

        18
  •  0
  •   Sassine Jaoude    6 年前

    我记得不久前我们在c/c++中构建dll和pdb时。

    我记得:

    • 添加日志数据有时会使bug移动或消失,或者出现完全不同的错误(因此这实际上不是一个选项)。
    • 我们通过运行边界检查器和简单地修复
    • 很多时候,我们系统地检查了代码并修复了字符分配。
    • 我的两分钱是,它与内存分配和管理以及调试模式和发布模式之间的约束和差异有关。

    然后继续经历这个循环。

    在处理这些bug时,为了不耽误生产,我们有时会临时将发布版本替换为DLL的调试版本。