通常,我必须在Windows上调试崩溃的C++程序才能重现崩溃,但是很难确定代码中的哪些指令序列导致崩溃(例如,另一个线程覆盖崩溃线程的内存)。在这种情况下,即使调用堆栈也无济于事。通常,我会通过注释掉源代码的各个部分来缩小崩溃原因,但这很繁琐。

有谁知道Windows的一个工具,可以在崩溃前立即报告或重放在所有线程中执行的最后几行源代码行或机器代码指令? IE。例如gdb的反向调试功能或Mutek的BugTrapper(不再可用)。我正在寻找一个发布且稳定的工具(我知道SoftwareVerify的“Bug Validator”和Hexray的IDA Pro 6.3 Trace Replayer,它们都仍处于封闭Beta程序中)。

我已经尝试过WinDbg跟踪命令wtta @$ra,但是这两个命令的缺点是它们会在几秒钟后自动停止。我需要跟踪命令一直运行到崩溃发生为止,并且跟踪正在运行的程序的所有线程。

注意:我不是,而是寻找旨在解决特定问题(例如gflags,pageheap,Memory Validator,Purify等)的调试工具。我正在寻找可释放或稳定的工具,以在指令级进行跟踪或重播。

最佳答案

万一您遇到another thread overwriting memory of the crashing thread,使用gflags(GFlags and PageHeap )很有用。它不会告诉您崩溃之前已经执行的几行操作,而是会告诉您确切的位置,即您的算法覆盖了正确分配的内存块的位置。

您首先激活以下类型的检查:
gflags /p /enable your_app.exe /fullgflags /p /enable your_app.exe /full /backwards
检查您是否已正确激活gflags /p
运行您的应用程序并收集转储文件

然后禁用使用gflags的检查:
gflags /p /disable your_app.exe
更新1
It does not immediately detect problems like *p = 0; where p is an invalid pointer至少检测到一些问题。
例如:

#include <stdio.h>
int main(int argc, char *argv[])
{
  int *p = new int;
  printf("1) p=%p\n",p);
  *p = 1;
  delete p;
  printf("2) p=%p\n",p);
  *p = 2;
  printf("Done\n");
  return 0;
}

当我在启用gflags的情况下运行时,会得到一个转储文件,并且可以正确识别问题:
STACK_TEXT:
0018ff44 00401215 00000001 03e5dfb8 03dfdf48 mem_alloc_3!main+0x5b [c:\src\tests\test.cpp\mem_alloc\mem_alloc\mem_alloc.3.cpp @ 11]
0018ff88 75f8339a 7efde000 0018ffd4 77bb9ef2 mem_alloc_3!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 586]
0018ff94 77bb9ef2 7efde000 2558d82c 00000000 kernel32!BaseThreadInitThunk+0xe
0018ffd4 77bb9ec5 004013bc 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
0018ffec 00000000 004013bc 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:  ~0s; .ecxr ; kb

FAULTING_SOURCE_CODE:
     7:   printf("1) p=%p\n",p);
     8:   *p = 1;
     9:   delete p;
    10:   printf("2) p=%p\n",p);
>   11:   *p = 2;
    12:   printf("Done\n");
    13:   return 0;
    14:
    15: }

更新2

@fmunkert的另一个示例:
#include <stdio.h>

int main()
{

        int *p = new int;
        printf("1) p=%p\n",p);
        *p = 1;
        p++;
        printf("2) p=%p\n",p);
        *p =  2;   // <==== Illegal memory access
        printf("Done\n");
        return 0;

}
gflags /p /enable mem_alloc.3.exe /full /unaligned
STACK_TEXT:
0018ff44 00401205 00000001 0505ffbe 04ffdf44 mem_alloc_3!main+0x52 [c:\src\tests\test.cpp\mem_alloc\mem_alloc\mem_alloc.3.cpp @ 12]
0018ff88 75f8339a 7efde000 0018ffd4 77bb9ef2 mem_alloc_3!__tmainCRTStartup+0x10f [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 586]
0018ff94 77bb9ef2 7efde000 2577c47c 00000000 kernel32!BaseThreadInitThunk+0xe
0018ffd4 77bb9ec5 004013ac 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
0018ffec 00000000 004013ac 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:  ~0s; .ecxr ; kb

FAULTING_SOURCE_CODE:
     8:         printf("1) p=%p\n",p);
     9:         *p = 1;
    10:         p++;
    11:         printf("2) p=%p\n",p);
>   12:         *p =  2;   // <==== Illegal memory access
    13:         printf("Done\n");
    14:         return 0;
    15:
    16: }

不幸的是,/unaligned 选项可能会导致程序无法正常运行(How to use Pageheap.exe):

10-05 17:46