C++ 使用Visual Studio调试器运行可执行文件与不使用调试器运行可执行文件的区别

C++ 使用Visual Studio调试器运行可执行文件与不使用调试器运行可执行文件的区别,c++,windows,visual-studio-2010,visual-studio,C++,Windows,Visual Studio 2010,Visual Studio,我正在尝试调试一个问题,其中一个可执行文件在直接从VisualStudio执行时会生成可重复的输出(我想要),但在从命令提示符执行时不会生成可重复的输出。它是一个单线程应用程序,因此在计时方面不应该有任何奇怪的行为 有人能列举这两种环境之间可能存在的差异吗 我确信实际的可执行文件是相同的——它们都是发布版本,并且运行相同的.exe文件 以下是环境和结果: 直接从命令提示符(cmd)运行:不可重复输出 从Visual Studio运行并进行调试(F5):可重复输出 从Visual Studio运行

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

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

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

以下是环境和结果:

  • 直接从命令提示符(cmd)运行:不可重复输出
  • 从Visual Studio运行并进行调试(F5):可重复输出
  • 从Visual Studio运行而不进行调试(Ctrl-F5):不可重复的输出
  • 我知道工作目录可能不同,但我正在手动调整,以确保工作目录相同

    基于这些结果,运行“带调试”(即使是在发布版本中)似乎在某种程度上解决了问题。这是否指向可能的罪犯?带调试运行可执行文件与不带调试运行可执行文件有什么区别

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

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

    要禁用此行为(以便在调试时发现问题),请将_NO_DEBUG_HEAP=1添加到环境中(如中)


    或者,您可以在程序执行的早期附加到进程。堆将不会进入调试模式。在执行开始的某个地方添加
    DebugBreak()
    行,使用Ctrl+F5运行,并在要求时开始调试。

    好吧,如果不了解更多关于代码的信息,很难说清楚。然而,我在一个做大量浮点算术(双精度数字)的程序中遇到了类似的问题

    当我处理的数字稍有不同,但在数字上无法与机器区分时,问题就会出现。 如果两个双精度的差值小于
    数值限制::epsilon()
    ,则它们被视为机器的相同数字。因此,该类型的表达式:

    if (num1==num2)...
    


    这取决于你的代码。您可能触发了未定义的行为,这只会在更高的优化级别出现。但理论上,不附加调试器不是唯一的区别吗?构建是相同的——两次发布构建。优化的程度没有改变。我知道你说你正在调整工作目录,但这似乎是罪魁祸首。我要寻找的另一个问题是安装库。VS处理依赖项(如果您通过ClickOnce构建和安装,则会处理依赖项),但直接在命令行上运行可能不会。我的VS已生锈,您确定它运行的是同一版本的可执行文件(与调试版本相反)?关于链接库呢?我的问题标题似乎不太准确——只要以两种不同的方式运行应用程序,这个问题就可以重现。如果我使用F5运行,我会得到想要的结果。如果使用Ctrl-F5运行,则无法获得所需的结果。因此,似乎与附加调试器有关的内容改变了可执行文件的行为。这将消除工作目录和链接库的问题,没有?伟大的链接添加,也有。对我来说,这似乎是一个非常可能的问题——某种类型的哨兵值,在附加调试器时可以重复,但在其他情况下只是垃圾数据(以及不可重复的行为!),这为我指明了正确的方向。我将用一些细节来编辑这个问题。谢谢
    if (num1<num2)...
    ...
    
    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;
    }