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