使用Visual Studio调试器与不使用调试器运行可执行文件之间的差异

时间:2013-05-22 15:59:19

标签: c++ windows visual-studio-2010 visual-studio

我正在尝试调试直接从Visual Studio执行时可执行文件生成可重复输出(我想要)的问题,但是当从命令提示符执行时,会产生可重复输出。它是一个单线程应用程序,所以在时间方面不应该有任何奇怪的行为。

有人可以列举两种环境之间可能存在的差异吗?

我确定实际的可执行文件是相同的 - 它们都是发布版本并且运行相同的.exe文件。

以下是环境和结果:

  1. 直接从命令提示符(cmd)运行:不可重复的输出
  2. 从带调试的Visual Studio运行(F5):可重复输出
  3. 从Visual Studio运行而不进行调试(Ctrl-F5):不可重复的输出
  4. 我知道工作目录可能有所不同,但是我手动调整它以确保工作目录是相同的。

    基于这些结果,看起来像运行“with Debugging”(即使在Release版本中)以某种方式修复了问题。这是否可能是罪魁祸首?运行可执行文件与调试之间有什么区别?

    解决方案:正如在接受的答案中指出的那样,调试堆就是问题所在。问题是我们代码的内部深处,有人在初始化之前访问大型数组的部分内容。他们已经用malloc分配了内存并且没有将内存初始化为0.调试堆将(我假设)用一些可重复的值填充数组,而当调试器没有附加时(即从命令行运行或与Ctrl-F5)值更随机,有时会导致程序行为的微小偏差。不幸的是,调整是如此微妙以至于几乎不可察觉,并且在处理的第一个“帧”之后,的存储器被正确地重置,但是初始条件已经略有不同并且损坏已经完成。混沌理论在行动!感谢您的指导。

    一个很好的调试技巧帮助:编写一个自定义的malloc,立即用完全随机的数据填充内存。这样,您可以确保在使用它之前自己正确地初始化它,否则每次运行它时(希望)结果都会疯狂 - 即使在调试模式下使用调试堆也是如此!

2 个答案:

答案 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++菜单的LinkerProperties部分查看不同编译选项和优化的效果。

为避免此问题,建议您使用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;
}