我正在尝试调试直接从Visual Studio执行时可执行文件生成可重复输出(我想要)的问题,但是当从命令提示符执行时,不会产生可重复输出。它是一个单线程应用程序,所以在时间方面不应该有任何奇怪的行为。
有人可以列举两种环境之间可能存在的差异吗?
我确定实际的可执行文件是相同的 - 它们都是发布版本并且运行相同的.exe文件。
以下是环境和结果:
我知道工作目录可能有所不同,但是我手动调整它以确保工作目录是相同的。
基于这些结果,看起来像运行“with Debugging”(即使在Release版本中)以某种方式修复了问题。这是否可能是罪魁祸首?运行可执行文件与调试之间有什么区别?
解决方案:正如在接受的答案中指出的那样,调试堆就是问题所在。问题是我们代码的内部深处,有人在初始化之前访问大型数组的部分内容。他们已经用malloc分配了内存并且没有将内存初始化为0.调试堆将(我假设)用一些可重复的值填充数组,而当调试器没有附加时(即从命令行运行或与Ctrl-F5)值更随机,有时会导致程序行为的微小偏差。不幸的是,调整是如此微妙以至于几乎不可察觉,并且在处理的第一个“帧”之后,的存储器被正确地重置,但是初始条件已经略有不同并且损坏已经完成。混沌理论在行动!感谢您的指导。
一个很好的调试技巧帮助:编写一个自定义的malloc,立即用完全随机的数据填充内存。这样,您可以确保在使用它之前自己正确地初始化它,否则每次运行它时(希望)结果都会疯狂 - 即使在调试模式下使用调试堆也是如此!
答案 0 :(得分:17)
Windows Heap behaves differently if process is started under the debugger.要禁用此行为(为了在调试时发现问题),请将_NO_DEBUG_HEAP = 1添加到环境中(如this question中所示)。
或者,您可以在程序执行的早期附加到进程。 Heap将不会进入调试模式。在执行开始时的某处添加DebugBreak()
行,使用Ctrl + F5运行,并在被要求时开始调试。
答案 1 :(得分:0)
嗯,如果不了解您的代码,很难说。但是,我有一个类似的问题,一个程序做了很多浮点算术(双精度数)。
当我处理稍微不同但在数字上与机器无法区分的数字时,问题会出现。
如果两个双精度相差小于numeric_limits<double>::epsilon()
,则它们被视为机器的相同数字。因此,类型的表达式:
if (num1==num2)...
或
if (num1<num2)...
...
可以产生丰富多彩的效果。
在调试或释放模式下运行时,这些彩色效果可能会有所不同。原因是调试/发布运行时库是不同的。而且,至关重要的是,编译是通过不同的代码优化完成的。命令行调试版本和调试窗口版本(F5)之间的差异也可以通过细微的优化差异来解释。
如果您正在使用VS,则可以在C/C++
菜单的Linker
和Properties
部分查看不同编译选项和优化的效果。
为避免此问题,建议您使用numeric_limits
STL库中的<limits>
工具。例如,一个小于运算符的实现应该是这样的:
bool operator<(double num1, double num2) {
double difference=fabs(num1-num2);
if (difference>numeric_limits<double>::epsilon()) {
if (num1 < num2) return true;
return false;
}
return false;
}