C++ 程序只在发布版本时崩溃--如何调试?

C++ 程序只在发布版本时崩溃--如何调试?,c++,debugging,C++,Debugging,我这里有一个“薛定谔猫”类型的问题——我的程序(实际上是我程序的测试套件,但仍然是一个程序)正在崩溃,但只有在以发布模式构建时,并且只有在从命令行启动时才会崩溃。通过caveman调试(即到处都是令人讨厌的printf()消息),我确定了代码崩溃的测试方法,但不幸的是,实际崩溃似乎发生在某些析构函数中,因为我看到的最后一条跟踪消息是在其他干净执行的析构函数中 当我尝试在VisualStudio中运行此程序时,它没有崩溃。从WinDbg.exe启动时也是如此。只有从命令行启动时才会发生崩溃。这是在

我这里有一个“薛定谔猫”类型的问题——我的程序(实际上是我程序的测试套件,但仍然是一个程序)正在崩溃,但只有在以发布模式构建时,并且只有在从命令行启动时才会崩溃。通过caveman调试(即到处都是令人讨厌的printf()消息),我确定了代码崩溃的测试方法,但不幸的是,实际崩溃似乎发生在某些析构函数中,因为我看到的最后一条跟踪消息是在其他干净执行的析构函数中

当我尝试在VisualStudio中运行此程序时,它没有崩溃。从WinDbg.exe启动时也是如此。只有从命令行启动时才会发生崩溃。这是在WindowsVista下发生的,顺便说一句,不幸的是,我现在没有权限在XP机器上进行测试

如果我能让Windows打印出一个堆栈跟踪,或者其他一些东西,而不是简单地终止程序,就好像它已经干净地退出了一样,那就太好了。有人对我如何在这里获得一些更有意义的信息并希望修复这个bug有什么建议吗


编辑:该问题确实是由越界数组引起的。谢谢大家帮我找到这个问题

以前我遇到过类似的问题,通常是由于变量初始化引起的。在调试模式下,变量和指针会自动初始化为零,但在发布模式下则不会。因此,如果您有这样的代码

int* p;
....
if (p == 0) { // do stuff }
在调试模式下,不会执行if中的代码,但在发布模式p中包含未定义的值,该值不太可能为0,因此执行该代码通常会导致崩溃


我会检查你的代码中是否有未初始化的变量。这也适用于数组的内容。

我曾经在GCC中遇到过类似的情况。结果证明,这是一个过于激进的优化,只有在创建最终版本时才启用,而不是在开发过程中启用

嗯,说实话,这是我的错,不是gcc的错,因为我没有注意到我的代码依赖于这样一个事实,即特定的优化是不会完成的


我花了很多时间去追踪它,而我只是因为我在一个新闻组上问了问题,有人让我想了想。所以,让我回敬你一句,以防这种情况也发生在你身上。

这样的崩溃几乎总是由IDE造成的,因为IDE通常会将未初始化变量的内容设置为零、null或其他类似的“合理”值,而在本机运行时,你会得到系统拾取的任何随机垃圾


因此,几乎可以肯定的是,您使用的错误就像在指针被正确初始化之前使用指针一样,并且您在IDE中侥幸逃脱,因为它不会指向任何危险的地方——或者该值是由错误检查处理的——但在发布模式下,它会做一些令人讨厌的事情。

您可以设置WinDbg作为你的验尸调试器。这将在崩溃发生时启动调试器并将其附加到进程。要安装WinDbg进行后期调试,请使用/I选项(注意它是大写的):

更多细节


至于原因,正如其他答案所示,它很可能是一个单位化变量。

我发现这对您的场景很有用。ISTR编译器选项有点过时。查看Visual Studio项目选项,了解如何为发布版本生成pdb文件等。

关于获取诊断信息的问题,您是否尝试过使用adplus.vbs作为WinDbg.exe的替代方案?要附加到正在运行的进程,请使用

adplus.vbs -crash -p <process_id>

有关adplus.vbs的完整信息,请访问:

,以便您可以分析崩溃转储:

  • 为您的代码生成pdb文件
  • 您可以重新设置基础,将exe和DLL加载到同一地址
  • 启用事后调试程序,例如
  • 使用工具(如)检查崩溃故障地址
  • 您还应该查看中的工具。 您可以监视应用程序并查看第二次机会异常之前的所有第一次机会异常


    希望在我看到或听到的100%个案例中有帮助。

    < p>,在调试程序中C或C++程序运行良好,但在运行时失败,原因是写在函数局部数组的末尾。(调试器会在堆栈上放置更多内容,因此您不太可能覆盖重要内容。)

    很可疑,它会发生在调试器外部而不是内部;在调试器中运行通常不会更改应用程序的行为。我将检查控制台和IDE之间的环境差异。另外,显然,在没有优化和调试信息的情况下编译发行版,看看这是否会影响行为。最后,请查看其他人在此建议的事后调试工具,通常您可以从中获得一些线索。

    即使您已将exe构建为发行版,您仍然可以生成PDB(程序数据库)文件,允许您堆叠跟踪,并执行有限数量的变量检查。 在您的构建设置中,有一个创建PDB文件的选项。打开此选项并重新链接。然后首先尝试从IDE运行,看看是否发生崩溃。如果是这样的话,那就太好了——你们都准备好看事情了。如果不是,则从命令行运行时,可以执行以下两项操作之一:

  • 运行EXE,并在崩溃之前执行“附加到进程”(VisualStudio上的“工具”菜单)
  • 崩溃后,选择启动调试器的选项
  • 当要求指向PDB文件时,请浏览以查找它们。如果PDB与EXE或DLL放在同一个输出文件夹中,它们可能会自动拾取

    PDB提供了一个到源的链接,其中包含足够的符号信息,以便能够看到堆栈tr
    adplus.vbs -crash -p <process_id>
    
    adplus.vbs -crash -sc your_app.exe
    
    long __stdcall MyFilter(EXCEPTION_POINTERS *) { HANDLE hEvt=::CreateEventW(0,1,0,0); if(hEvt) { if(WAIT_FAILED==::WaitForSingleObject(hEvt, INFINITE)) { //log failure } } } // somewhere in your wmain/WinMain: SetUnhandledExceptionFilter(MyFilter);
    char *end = static_cast<char*>(attr->data) + attr->dataSize;
    
    char *end = static_cast<char*>(attr->data) + attr->dataSize - 1;
    
    char a[8];
    memset(&a[0], 0, 16);
    
    : /*use array a doing some thing */