c#/C++混合编程的一个问题
关于std::__non_rtti_object异常
什么是std::__non_rtti_object异常?
不是一个RTTI对象异常
继承关系:
__non_rtti_object : public bad_typeid
备注
当指针指向的是一个无效的对象,引发此异常。例如,它是一个错误的指针,或者代码不是用/GR编译的
仅通过转储来排除内存泄漏
有时我们会遇到这样一个场景:一个进程正在使用大量内存,而此时我们能够获得的唯一数据就是用户转储。通常,来自umdh或xperf等工具的数据会更好,因为它们提供一段时间内的内存使用数据,并且可以包括调用堆栈信息。但是,umdh需要重新启动进程(这会丢失高内存使用率的状态),xperf需要安装Windows Performance Toolkit,这可能并不总是一个立即的选项。
当我们有这样一个转储时,我们可能无法明确指出是哪段代码产生了高内存使用率,但我们可以将故障排除的范围缩小到特定的dll。我们需要做的第一件事是确定什么类型的内存使用了大部分地址空间。调试器命令!address -summary允许我们执行以下操作:
0:000> !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 489 7fe`6ff5a000 ( 7.994 Tb) 99.92%
Heap 9094 1`75ed1000 ( 5.843 Gb) 93.47% 0.07%
<unknown> 275 0`12e41000 ( 302.254 Mb) 4.72% 0.00%
Image 937 0`05a6a000 ( 90.414 Mb) 1.41% 0.00%
Stack 138 0`01700000 ( 23.000 Mb) 0.36% 0.00%
Other 14 0`001bd000 ( 1.738 Mb) 0.03% 0.00%
TEB 46 0`0005c000 ( 368.000 kb) 0.01% 0.00%
PEB 1 0`00001000 ( 4.000 kb) 0.00% 0.00%
从这个例子中我们可以看到大部分内存被堆使用。一个进程通常有多个堆,每个堆都是通过调用HeapCreate创建的。我们可以检查这些堆的大小!heap -s:
0:000> !heap -s
LFH Key : 0x0000006c1104d280
Termination on corruption : ENABLED
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-------------------------------------------------------------------------------------
0000000000100000 00000002 16384 12824 16384 1180 254 5 0 3 LFH
0000000000010000 00008000 64 4 64 1 1 1 0 0
00000000003d0000 00001002 1088 708 1088 121 20 2 0 0 LFH
0000000003080000 00001002 1536 700 1536 4 4 2 0 0 LFH
00000000033a0000 00001002 5229696 1377584 5229696 414244 4039 3059 0 2c LFH
External fragmentation 30 % (4039 free blocks)
Virtual address fragmentation 73 % (3059 uncommited ranges)
0000000003380000 00001002 64 8 64 3 1 1 0 0
0000000003600000 00001002 512 56 512 3 1 1 0 0
0000000003c20000 00001002 512 8 512 3 1 1 0 0
0000000003220000 00001002 512 8 512 3 1 1 0 0
0000000003e50000 00001002 512 8 512 3 1 1 0 0
0000000003d00000 00001002 512 148 512 5 3 1 0 0 LFH
从上面的输出中我们可以看到大部分内存被堆00000000033a0000占用。在这一点上,我们需要尝试确定这个堆的用途。执行此操作的一种强力方法是使用“s”命令搜索内存。
0:000> s -q 0 l?7fffffffffffffff 00000000033a0000
....
000007fe`f21810a0 00000000`033a0000 00000000`00000001
关于异常STATUS_VERIFIER_STOP(0xC0000421)
简介
STATUS_VERIFIER_STOP异常表示因Application verifier(应用程序验证器) 在当前进程找到一个错误而停止.。值为0xC0000421。其定义如下:
//
// MessageId: STATUS_VERIFIER_STOP
//
// MessageText:
//
// Application verifier has found an error in the current process.
//
#define STATUS_VERIFIER_STOP ((NTSTATUS)0xC0000421L)
说明
此异常一定要使用Application verifier或Gflags.exe等工具对特定程序做相关的设置才会产生。
异常结构
ExceptionAddress: 6f59df82 (verifier!VerifierStopMessage+0x00000052)
ExceptionCode: c0000421 (Verifier stop)
ExceptionFlags: 00000000
NumberParameters: 6
Parameter[0]: 32725641//可能是个魔数,有知道的同行指正。
Parameter[1]: 0000000f//StopCode,0xf---表示堆块后缀填充被破坏
Parameter[2]: 00d01000//Heap句柄
Parameter[3]: b2bfab10//用户内存开始地址
Parameter[4]: 000001c8//用户内存size
Parameter[5]: b2bfacd8//用户内存结束地址
当然上面的参数个数和具体内容是由StopCode决定的,不唯一。具体的后面有时间的话会有相关文章
Windbg命令系列---.printf
.printf的行为跟C语言的printf函数类似。
语法
.printf [/D] [Option] "FormatString" [, Argument , ...]