发布构建的运行方式与Debug构建不同的是什么原因 [英] What are some reasons a Release build would run differently than a Debug build

查看:219
本文介绍了发布构建的运行方式与Debug构建不同的是什么原因的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Visual Studio 2005 C ++程序,在发布模式下运行与在调试模式下不同。在释放模式下,有一个(明显的)间歇性崩溃发生。在调试模式下,它不会崩溃。发布版本与Debug版本不同的原因是什么?

I have a Visual Studio 2005 C++ program that runs differently in Release mode than it does in Debug mode. In release mode, there's an (apparent) intermittent crash occurring. In debug mode, it doesn't crash. What are some reasons that a Release build would work differently than a Debug build?

还值得一提的是我的程序相当复杂,并且使用多个第三方库进行XML处理,消息代理等。

It's also worth mentioning my program is fairly complex and uses several 3rd party libraries for XML processing, message brokering, etc...

提前感谢!

推荐答案

存续发布版本 提供了一个很好的概述。

Surviving the Release Version gives a good overview.

我遇到的问题 - 大部分已提及

Things I have encountered - most are already mentioned

变量初始化
到目前为止最常见。在Visual Studio中,调试构建明确地将分配的内存初始化为给定的值,参见例如。此处内存值。这些值通常容易发现,当用作索引或作为指针时作为访问冲突时,导致超出范围的错误。一个未初始化的布尔值是真的,但是,可能会导致未初始化的内存错误未检测到多年。

Variable initialization by far the most common. In Visual Studio, debug builds explicitely initialize allocated memory to given values, see e.g. Memory Values here. These values are usually easy to spot, cause an out of bounds error when used as an index or an access violation when used as a pointer. An uninitialized boolean is true, however, and may cause uninitialized memory bugs going undetected for years.

在发布版本中内存不明确初始化,它以前。这会导致有趣的值和随机崩溃,但通常是确定性崩溃,需要一个明显不相关的命令在实际崩溃的命令之前执行。这是由第一个命令用特定值设置存储器位置引起的,并且当存储器位置被循环时,第二个命令将它们视为初始化。这是更常见的未初始化的堆栈变量比堆,但后者也发生在我身上。

In Release builds where memory isn't explicitely initialized it just keeps the contents that it had before. This leads to "funny values" and "random" crashes, but as often to deterministic crashes that require an apparently unrelated command to be executed before the command that actually crashes. This is caused by the first command "setting up" the memory location with specific values, and when the memory locations are recycled the second command sees them as initializations. That's more common with uninitialized stack variables than heap, but the latter has happened to me, too.

原始内存初始化也可以是不同的发布版本无论你从visual studio(调试器附加)vs从开始。这使得最好的类型的发布构建错误,从来不会出现在调试器下。

Raw memory initialization can also be different in a release build whether you start from visual studio (debugger attached) vs. starting from explorer. That makes the "nicest" kind of release build bugs that never appear under the debugger.

有效优化在我的优势中排名第二。 C ++标准允许进行许多优化,这可能是令人惊讶的,但是是完全有效的。当两个指针别名相同的存储器位置时,不考虑初始化的顺序,或者多个线程修改相同的存储器位置,并且期望线程B看到线程A所做的改变的特定顺序。通常,编译器被指责这些。不是那么快,年轻的yedi! - 见下面

Valid Optimizations come second in my exeprience. The C++ standard allows lots of optimizations to take place which may be surprising but are entirely valid e.g. when two pointers alias the same memory location, order of initialization is not considered, or multiple threads modify the same memory locations, and you expect a certain order in which thread B sees the changes made by thread A. Often, the compiler is blamed for these. Not so fast, young yedi! - see below

计时发布版本不只是运行速度更快,原因有很多种(优化,日志功能提供线程同步点,调试代码,如断言未执行等),操作之间的相对定时也显着变化。最常见的问题是竞争条件,还有死锁和简单的不同顺序执行消息/定时器/基于事件的代码。即使他们是时间问题,他们可以令人惊讶的稳定跨版本和平台,复制品工作总是,除了PC 23。

Timing Release builds don't just "run faster", for a variety of reasons (optimizations, logging functions providing a thread sync point, debug code like asserts not executed etc.) also the relative timing between operations change dramatically. Most common problem uncovered by that is race conditions, but also deadlocks and simple "different order" execution of message/timer/event-based code. Even though they are timing problems, they can be surprisingly stable across builds and platforms, with reproductions that "work always, except on PC 23".

保护字节。调试构建通常对所选实例和分配放置(更多)保护字节,以防止索引溢出和有时下溢。在代码依赖于偏移或大小的罕见情况下,序列化原始结构,它们是不同的。

Guard Bytes. Debug builds often put (more) guard bytes around selected instances and allocations, to protect against index overflows and sometimes underflows. In the rare cases where the code relies on offsets or sizes, e.g. serializing raw structures, they are different.

其他代码差异某些说明(例如声明)在发布版本中无效。有时他们有不同的副作用。这是宏观欺骗,如在经典(警告:多个错误)

Other code differences Some instructions - e.g asserts - evaluate to nothing in release builds. Sometimes they have different side effects. This is prevalent with macro trickery, as in the classic (warning: multiple errors)

#ifdef DEBUG
#define Log(x) cout << #x << x << "\n";
#else 
#define Log(x)
#endif

if (foo)
  Log(x)
if (bar)
  Run();

其中,在发布版本中,计算为 if(foo&&
这种类型的错误对于正常的C / C ++代码和正确写入的宏非常罕见。

Which, in a release build, evaluates to if (foo && bar) This type of error is very very rare with normal C/C++ code, and macros that are correctly written.

编译器错误这真的永远不会发生。好吧 - 它是,但你是你的职业生涯的大部分更好地假设它不。在使用VC6的十年中,我发现了一个我仍然相信这是一个不固定的编译器错误,与几十个模式(甚至几百个实例)不足的理解经验(a.k.a.标准)相比。

Compiler Bugs This really never ever happens. Well - it does, but you are for the most part of your career better off assuming it does not. In a decade of working with VC6, I found one where I am still convinced this is an unfixed compiler bug, compared to dozens of patterns (maybe even hundreds of instances) with insufficient understanding of the scripture (a.k.a. the standard).

这篇关于发布构建的运行方式与Debug构建不同的是什么原因的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆