在发布编译模式下出现的程序错误和异常行为,而在调试模式下却没有出现,这通常是由于哪些原因引起的?
在发布编译模式下出现的程序错误和异常行为,而在调试模式下却没有出现,这通常是由于哪些原因引起的?
在C++中的调试模式下,很多时候所有变量都会被初始化为null值,而在发布模式下则不会,除非明确声明。
检查是否有调试宏和未初始化的变量。
如果程序使用了线程,则优化也可能导致发布模式下出现一些问题。
还要检查所有异常,例如与发布模式没有直接关系,但有时我们会忽略一些关键的异常,比如在VC++中的内存访问冲突,但同样的问题在其他操作系统(如Linux、Solaris)中可能是个问题。理想情况下,程序不应该捕获此类关键异常,例如访问空指针。
一个常见的陷阱是在ASSERT内部使用具有副作用的表达式。
assert(MyObj->LoadFromFile(File));
。在发布版本中,LoadFromFile根本不会被调用,而且你在编译时也不会得到任何通知。 - Benlitz我过去曾遇到多个被调试版通过但发布版中崩溃的问题。 这其中有很多潜在原因(包括当然已在此主题中总结的原因),我曾遇到以下所有情况:
#ifdef _DEBUG
中,因此在调试版本中类的大小不同。 有时在发布版本中使用#ifndef NDEBUG
#ifdef
#pragma pack
这样未被重置的东西,那么可能会导致严重问题。 使用预编译头文件和强制包含也可能出现类似问题这些年我积累了一些有助于解决调试/发布错误的技巧:
其他可能存在的区别包括:
GC::KeepAlive
的帮助就很有用了:https://msdn.microsoft.com/zh-cn/library/system.gc.keepalive(v=vs.110).aspx - stusmith是的!如果您有条件编译,则可能存在时间错误(优化后的发布代码与非优化的调试代码之间),内存重用与调试堆。
如果你在C领域中,它可能会有影响。
一种可能的原因是DEBUG版本可能添加了代码来检查杂散指针并保护您的代码免于崩溃(或行为不正确)。如果是这种情况,您应该仔细检查编译器给出的警告和其他消息。
另一个可能的原因是优化(通常在发布版本上开启,在调试模式下关闭)。代码和数据布局可能已经被优化,而你的调试程序只是访问未使用的内存,发布版本现在正在尝试访问保留的内存甚至指向代码!
编辑:我看到其他人提到了:当没有在DEBUG模式下编译时,你可能会完全排除某些代码部分。如果是这种情况,我希望那确实是调试代码,而不是程序本身正确性所必需的重要内容!
CRT库函数在debug和release模式下的行为是不同的(/MD和/MDd)。
例如,调试版本通常会预先填充您传递给指定长度的缓冲区,以验证您的声明。例如strcpy_s
、StringCchCopy
等。即使字符串提前终止,您的szDest也必须是n个字节长!
Sure, for example, if you use constructions like
#if DEBUG
//some code
#endif
你需要提供更多的信息,但是是可以做到的。这取决于你的调试版本所做的事情。你可能会在其中记录或添加额外的检查,这些内容不会编译到发布版本中。这些仅用于调试的代码路径可能会产生意想不到的副作用,从而以奇怪的方式改变状态或影响变量。调试构建通常运行较慢,因此这可能会影响线程并隐藏竞争条件。同样适用于来自发布编译的简单优化,这是可能的(尽管现在不太可能),发布编译可能会将某些东西作为优化而短路。
如果没有更多细节,我会假设“不好”意味着它不能编译或在运行时引发某些错误。检查一下你的代码是否依赖于编译版本,可以通过#if DEBUG
语句或标记有Conditional
属性的方法来实现。