【发布时间】:2013-05-17 18:44:32
【问题描述】:
我正在尝试调试一个问题,即当直接从 Visual Studio 执行时,可执行文件会产生可重复的输出(我想要的),但从命令提示符执行时不会产生可重复的输出。这是一个单线程应用程序,因此在时间方面不应该有任何奇怪的行为。
有人能列举出这两种环境之间可能存在的差异吗?
我确定实际的可执行文件是相同的——它们都是发布版本并且运行相同的 .exe 文件。
这里是环境和结果:
- 直接从命令提示符 (cmd) 运行:不可重复输出
- 通过调试 (F5) 从 Visual Studio 运行:可重复输出
- 从 Visual Studio 运行而不进行调试 (Ctrl-F5):不可重复的输出
我知道工作目录可能不同,但我正在手动调整它以确保工作目录相同。
根据这些结果,看起来运行“带调试”(即使在发布版本中)以某种方式解决了问题。这是否指向一个可能的罪魁祸首?运行带调试和不带调试的可执行文件有什么区别?
解决方案: 正如接受的答案中所指出的,调试堆是问题所在。问题是在我们代码的深处,有人在初始化之前访问了一个大数组的一部分。他们已经用 malloc 分配了内存并且没有将内存初始化为 0。调试堆(我假设)会用一些可重复的值填充数组,而当没有附加调试器时(即从命令行运行或使用Ctrl-F5)这些值更加随机,有时会导致程序行为的微小偏差。不幸的是,调整是如此微妙以至于几乎无法察觉,并且在处理的第一个“帧”之后,有问题的内存被正确重置,但初始条件已经略有不同,损坏已经完毕。混沌理论在行动!感谢您的指导。
一个很有帮助的调试技巧:编写一个自定义 malloc,立即用完全随机的数据填充内存。这样,您可以确保在使用它之前自己正确初始化它,否则每次运行它时您的结果都会(希望)很疯狂——即使在调试模式下使用调试堆!
【问题讨论】:
-
取决于您的代码。您可能会触发未定义的行为,只会在更高的优化级别出现。
-
但理论上不是没有附加调试器的唯一区别?构建是相同的——两次发布构建。优化程度没有改变。
-
我知道你说你正在调整工作目录,但这似乎是罪魁祸首。我要寻找的另一个问题是安装的库。 VS 处理依赖项(如果你通过 ClickOnce 构建和安装,它会处理你的依赖项),但直接在命令行上运行可能不会。
-
我的 VS 生锈了,您确定它运行的是相同的发布可执行文件(而不是调试版本)吗?链接库呢?
-
看来我的问题标题实际上不太准确 - 只需以两种不同的方式运行应用程序即可重现该问题。如果我用 F5 运行,我会得到我想要的结果。如果我使用 Ctrl-F5 运行,我不会得到我想要的结果。所以似乎与附加调试器相关的东西会改变可执行文件的行为。这应该消除工作目录和链接库的问题,不是吗?
标签: c++ windows visual-studio-2010 visual-studio