Application|Application Verifier 工具及指南


【Application|Application Verifier 工具及指南】这个工具的作用是用于判断一个wince的AP及其组件对内存堆的分配释放,对句柄的创建销毁进行检查,对AP退出后没有释放的内存堆和句柄log出来,帮助开发者分析问题解决问题。
当然对驱动它也可以搞定,我本人还木搞懂,所以先捂着还没热的一点经验,给大家一些引导,一是让大家知道有这么个东西(昨天我还不知道有这么个东西呢,嘿嘿),而是让大家知道怎么能最快用起这个东西,三是让大家知道怎么它的log。

1.先把设备端的目录拷贝到设备上执行,看到下面的对话框,呵呵,你的屏幕一定要够大才行哦。

勾上要执行的hook,然后点击add来添加需要检查的exe,如图。
2.从对话框里面选择要添加的exe

3.新exe会出现在list列表,选择后点击run,如图。

点击run后你的exe就运行起来了,模拟运行一段时间后关闭你的exe,记住一定要正常关闭,不能kill掉。
这个时候会在根目录生成一个Appverifier_XXX.log的文件,这就是输出的结果。
这个log文件你可以直接看,也可以用一个更加一目了然的工具来看。
就是1楼我提供的PC端的viewer,你只需要把这个log拷贝到pc上即可。
你的exe及其它调用的dll最好有编译的时候生成的map文件,如果有map档,viewer会帮会给你提供一个很重要的功能:从地址解析symbols,所以会告诉你具体哪个函数在做坏事。

现在教你怎么看log。
我们先打比方我们的exe里面做了下面的坏事:

  1. 测试代码
  2. void LeakMemory()
  3. {
  4. BYTE* p = new BYTE[10];
  5. NKDbgPrintfW(L"Allocated memory: 0x%X", p);
  6. }
  7. void LeakHandle()
  8. {
  9. HANDLE h = CreateEvent(NULL, FALSE, FALSE, L"leaked_event");
  10. NKDbgPrintfW(L"Created event: 0x%X", h);
  11. }
  12. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
  13. {
  14. LeakMemory();
  15. LeakHandle();
  16. return 0;
  17. }

那么会得到类似下面的log
1532862 PID:206001e TID:207001e Allocated memory: 0x2C022DD0 //这两行是程序输出的
1532878 PID:206001e TID:207001e Created event: 0x521603
1532985 PID:206001e TID:207001e Application verifier core unloaded from: leak.exe - 11:39:44 PM
1533001 PID:206001e TID:207001e DLL_PROCESS_DETACH: Shim_heap checking for abandoned heaps/allocations...
1533094 PID:206001e TID:207001e Heap statistics for heap 0x2c020010:
1533108 PID:206001e TID:207001eInitial size: 0, Maximum size: 0
1533122 PID:206001e TID:207001eCurrent bytes: 10, Max: 10
1533136 PID:206001e TID:207001eCurrent count: 1, Max: 1
1533150 PID:206001e TID:207001eFree list bytes: 0
1533164 PID:206001e TID:207001eFree list size: 0
1533183 PID:206001e TID:207001e Checking for un-freed items in heap 0x2c020010...
1533244 PID:206001e TID:207001e ----------------------------------------
1533260 PID:206001e TID:207001e TrackedItem count: 1
1533273 PID:206001e TID:207001e Callstack:
1533368 PID:206001e TID:207001e Console NOT redirected for process 0x206001E
1533506 PID:400002 TID:207001e RELFSD: Opening file shim_heap.map from desktop
1535138 PID:206001e TID:207001e0x41e98310: shim_heap.dll!APIHook_HeapAlloc + 5d0h
1535220 PID:206001e TID:207001e0x41e9b378: shim_heap.dll!APIHook_LocalAlloc + a8h
1535303 PID:206001e TID:207001e0x41e9c2f4: shim_heap.dll!APIHook_malloc + 18h
1535392 PID:206001e TID:207001e0x41e9c54c: shim_heap.dll!APIHook_new + 14h
1535596 PID:400002 TID:207001e RELFSD: Opening file leak.map from desktop
1535746 PID:206001e TID:207001e0x000110e0: leak.exe!?LeakMemory@@YAXXZ + ch //这是内存泄漏的调用栈
1535892 PID:206001e TID:207001e0x0001116c: leak.exe!WinMain + 10h
1536088 PID:206001e TID:207001e0x00011208: leak.exe!WinMainCRTStartupHelper + 28h
1536210 PID:206001e TID:207001e0x000111cc: leak.exe!WinMainCRTStartup + 20h
1536341 PID:400002 TID:207001e RELFSD: Opening file coredll.map from desktop
1546679 PID:206001e TID:207001e0x40071f5c: coredll.dll!MainThreadBaseFunc + 2a0h
1546768 PID:206001e TID:207001e Un-freed items:
1546854 PID:206001e TID:207001e0x2c022dd010 bytes, process: 0x0206001e, thread://泄漏的内存地址和大小,可以看出和程序里的一致0x0207001e, PerfCount: 1021127120
1546941 PID:206001e TID:207001eTotal: 10 bytes
1547026 PID:206001e TID:207001e Checking for leaks in marshall helper api's...
1547043 PID:206001e TID:207001e ------------------------------------------------------------------------
1547045 PID:206001e TID:207001e Shim HLeak detaching from process /Release/leak.exe
1547046 PID:206001e TID:207001e Num of un-freed handles = 1
1547046 PID:206001e TID:207001e Check log file for details
1547046 PID:206001e TID:207001e ------------------------------------------------------------------------
1547047 PID:206001e TID:207001e ----------------------
1547256 PID:206001e TID:207001e EVENT Handle = 0x00521603 Name: 'leaked_event' PerfCount: 1021895588 //泄漏的句柄,可以看出何程序里是一样的1547338 PID:206001e TID:207001e Callstack:
1547430 PID:400002 TID:207001e RELFSD: Opening file shim_hleak.map from desktop
1548302 PID:206001e TID:207001e0x41e84814: shim_hleak.dll!My_TrackerInsertItem2 + e0h
1548409 PID:206001e TID:207001e0x41e84710: shim_hleak.dll!My_TrackerInsertItem + 24h
1548486 PID:206001e TID:207001e0x41e84c00: shim_hleak.dll!APIHook_CreateEventW + 68h
1548653 PID:206001e TID:207001e0x0001112c: leak.exe!?LeakHandle@@YAXXZ + 18h //泄漏句柄的调用栈1548819 PID:206001e TID:207001e0x00011170: leak.exe!WinMain + 14h
1548979 PID:206001e TID:207001e0x00011208: leak.exe!WinMainCRTStartupHelper + 28h
1549136 PID:206001e TID:207001e0x000111cc: leak.exe!WinMainCRTStartup + 20h
1549219 PID:206001e TID:207001e0x40071f5c: coredll.dll!MainThreadBaseFunc + 2a0h

1549240 PID:206001e TID:207001e DLL_PROCESS_DETACH: Shim_usergdi checking for abandoned resources...
1549340 PID:206001e TID:207001e --------------------------------------------------------------------------------
1549355 PID:206001e TID:207001e VLOG exiting - check for verifier logs (22 info, 5 warnings, 0 errors)
1549368 PID:206001e TID:207001eProcess log: /release/AppVerifier_leak_2339.log //这是日志文件,文本格式,可以直接打开看
1549381 PID:206001e TID:207001e --------------------------------------------------------------------------------

粗体字部分就是log里面告诉我们有内存或句柄问题的位置。定位粗体部分的位置很简单,就是看每个callstack的shim_xxx.dll开头尾随的第一句话。

如果用viewer看,会清晰一些,下图是随便抓的一个sample:

heap的创建位置就是红线所画,但是它一直没有被释放直到程序退出。

    推荐阅读