gpt4 book ai didi

c++ - 如何记录或重播崩溃前立即执行的行或指令

转载 作者:可可西里 更新时间:2023-11-01 12:42:37 26 4
gpt4 key购买 nike

我经常需要在 Windows 上调试崩溃的 C++ 程序,以便重现崩溃,但很难确定代码中的指令序列导致了崩溃(例如,另一个线程覆盖了崩溃线程的内存)。在这种情况下,即使调用堆栈也无济于事。通常我会通过注释掉部分源代码来缩小崩溃原因的范围,但这非常乏味。

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

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

注意:我不是在寻找一种调试工具来解决特定问题,例如 gflags、pageheap、Memory Validator、Purify 等。我正在寻找已发布且稳定的工具,用于在指令级别进行跟踪或重放。

最佳答案

如果您遇到另一个线程覆盖崩溃线程的内存,使用gflags 会很有用。 (GFlags and PageHeap )。它不会告诉您崩溃前已执行的几行代码,而是会准确告诉您您的算法覆盖了正确分配的内存块的位置。

您首先激活这种类型的检查:

gflags/p/enable your_app.exe/full
gflags/p/enable your_app.exe/full/backwards

检查您是否已正确激活
gflags/p

运行你的应用程序并收集转储文件

然后禁用 gflags 检查:

gflags/p/disable your_app.exe


更新 1

它不会立即检测到类似 *p = 0 的问题;其中 p 是无效指针
至少检测到一些问题。
例如:

#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):

Some programs make assumptions about 8-byte alignment and they stop working correctly with the /unaligned parameter. Microsoft Internet Explorer is one such program.

关于c++ - 如何记录或重播崩溃前立即执行的行或指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10912191/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com