利用压力测试来保证软件的质量(四) 内存泄露问题
2010-09-10 21:15 王克伟 阅读(1113) 评论(0) 编辑 收藏 举报内存泄露
这是实际产品中的一个严重的内存泄漏的Bug,这样描述的:
[MemoryLeak] Memory comsuption keeps inscreasing when open/close applications. We saw similar issue on several different applications. Here's some data for WMP and Calculator:
WMP:
Iteration 0 1 2 3 4 5 6 7 8 9 10
Free Mem (MB) 133.83 133.51 133.33 133.17 132.94 132.80 132.64 132.48 132.32 132.16 132.00
Calculator:
Iteration 0 1 2 3 4 5 6 7 8 9 10
Free Mem (MB) 133.88 133.13 132.92 132.80 132.66 132.55 132.46 132.33 132.21 132.10 131.98
泄露发生在private/shellw/gserver/shell32g/san_cmn.cpp L275:
static BOOL FreeAppData( SANMSG *psm ) { BOOL dwRes = FALSE; DWORD dwExitCode; HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, psm->dwProcessID); if( psm->pvAppData && (hProcess && GetExitCodeProcess( hProcess, &dwExitCode)) && STILL_ACTIVE == dwExitCode ) { switch (psm->dwNotify) { case SAN_NOTIFY_LAUNCH: __try { dwRes = !RemoteHeap::LocalFree(psm->pvAppData, psm->dwProcessID); psm->pvAppData = NULL; } __except(WatsonReportFault(GetExceptionInformation(), EXCEPTION_EXECUTE_HANDLER)) { DEBUGMSG(ZONE_SAN,(TEXT("freeappdata threw exception.\r\n"))); dwRes = FALSE; } break; } //CloseHandle(hProcess); } if (hProcess) CloseHandle(hProcess); //应该在此位置关闭进程的句柄!一个疏忽造成了很严重的内存泄露。 return dwRes; }
我查一下,这个问题在移植过程中疏忽造成的(不断的代码修改造成的,看来纵有百虑总有一疏啊)。
FreeAppData API在程序启动时会调用,而在关闭程序时不会调用,比如启动WMP时:
SHELL32!FreeAppData(SANMSG * 0x007ab720) line 253 SHELL32!XSHAppNotifyDone(HWND__ * 0x700578a0, long 0x00000000, unsigned long 0x00000001, void * 0x009dfc30) line 176 + 12 bytes AYGSHELL!xxx_SHAppNotifyDone(HWND__ *, long, unsigned long, void *) line 40 + 23 bytes WMPOCX!CPlayerWindow::OnSANMessage(HWND__ *, unsigned int, long, bool &) line 1104 + 20 bytes WMPOCX!CPlayerWindow::WndProc(HWND__ *, unsigned int, unsigned int, long) line 143 + 44 bytes GWES!WindowProcCallback(void * 0x07f60102, long (HWND__ *, unsigned int, unsigned int, long)* 0x423637c0, CWindow * 0x700578a0, unsigned int 0x0000c003, unsigned int 0x00000003, long 0x00000000, bool * 0xd890fb53) line 3198 + 21 bytes GWES!CWindow::CallWindowProcW_I(CePtr_t<long (__cdecl*)(HWND__ *,unsigned int,unsigned int,long)> {...}, HWND__ * 0x700578a0, unsigned int 0x0000c003, unsigned int 0x00000003, long 0x00000000, SendMsgEntry_t * 0x00000000) line 3403 + 33 bytes GWES!MsgQueue::DispatchMessageW_I(const tagMSG * 0x0003fb50) line 4967 + 38 bytes GWES!PixelDoubled_t::DispatchMessageW_I(const tagMSG * 0x0003fb50) line 2083 + 15 bytes COREDLL!DispatchMessageW(const tagMSG *) line 2947 + 9 bytes WMPOCX!StartThePlayer(HINSTANCE__ *, int) line 92 + 9 bytes WMPLAYER!PlayerEntry() line 99 + 9 bytes COREDLL!MainThreadBaseFunc(void *, const wchar_t *, const wchar_t *, HINSTANCE__ *, HINSTANCE__ *, HINSTANCE__ *) line 1072 + 60 bytes
奇怪的是启动IE时不会调用到这个API,而启动闹铃时会:
SHELL32!FreeAppData(SANMSG * 0x009b2940) line 253 SHELL32!XSHAppNotifyDone(HWND__ * 0x70053000, long 0x00000000, unsigned long 0x00000001, void * 0x009dfc30) line 176 + 12 bytes AYGSHELL!xxx_SHAppNotifyDone(HWND__ *, long, unsigned long, void *) line 40 + 23 bytes CLOCKDLL!HandleSAN_NOTIFY(tagAppState *, HWND__ *, unsigned int, long) line 1095 + 20 bytes CLOCKDLL!WndProc(HWND__ *, unsigned int, unsigned int, long) line 1390 + 21 bytes GWES!WindowProcCallback(void * 0x011a002a, long (HWND__ *, unsigned int, unsigned int, long)* 0x417a34a0, CWindow * 0x70053000, unsigned int 0x0000c003, unsigned int 0x00000003, long 0x00000000, bool * 0xd76ffb53) line 3198 + 21 bytes GWES!CWindow::CallWindowProcW_I(CePtr_t<long (__cdecl*)(HWND__ *,unsigned int,unsigned int,long)> {...}, HWND__ * 0x70053000, unsigned int 0x0000c003, unsigned int 0x00000003, long 0x00000000, SendMsgEntry_t * 0x00000000) line 3403 + 33 bytes GWES!MsgQueue::DispatchMessageW_I(const tagMSG * 0x0002f9dc) line 4967 + 38 bytes GWES!PixelDoubled_t::DispatchMessageW_I(const tagMSG * 0x0002f9dc) line 2083 + 15 bytes COREDLL!DispatchMessageW(const tagMSG *) line 2947 + 9 bytes COMMCTRL!_RealPropertySheet(PROPDATA *) line 3821 + 9 bytes COMMCTRL!PropertySheetW(const _PROPSHEETHEADERW *) line 3992 + 9 bytes CLOCKDLL!DisplayPropSheet(HWND__ *, tagAppState *) line 187 + 13 bytes CLOCKDLL!StartClock(HINSTANCE__ *, unsigned short *, int, HINSTANCE__ *) line 754 + 16 bytes CLOCK!WinMain(HINSTANCE__ *, HINSTANCE__ *, unsigned short *, int) line 27 + 21 bytes COREDLL!MainThreadBaseFunc(void *, const wchar_t *, const wchar_t *, HINSTANCE__ *, HINSTANCE__ *, HINSTANCE__ *) line 1072 + 60 bytes
当然健全的测试机制是发现这些内存泄漏的问题的前提。
出处: http://wangkewei.cnblogs.com/
版权声明: 本文的版权归作者与博客园共有。转载时须注明本文的详细链接,否则作者将保留追究其法律责任的权利。
您可以从这里更方便的找到我的文章。