【资料图】
Release版VC6 MFC程序 程序正常退出时得到一个如下异常调用栈:
0:000> kb # ChildEBP RetAddr Args to Child WARNING: Frame IP not in any known module. Following frames may be wrong.00 0019eb94 76124f2f 00c3afc8 0019ebdc 0019ebb8 0x8c73d0101 0019ebdc 0079451a 00c3afc8 73d82ec0 00000001 USER32!IsZoomed+0xaf02 0019ebe4 73d82ec0 00000001 73d35d1c 00c3afc8 JXC_MED!CMainFrame::`scalar deleting destructor"+0x803 0019ebec 73d35d1c 00c3afc8 00000000 73d35c0f MFC42!CControlFrameWnd::PostNcDestroy+0xb04 0019ec2c 73d31e1d 00c3afc8 00c3afc8 00cae670 MFC42!CWnd::OnNcDestroy+0x10d05 0019eca4 73d31b07 00000082 00000000 73dca448 MFC42!CWnd::OnWndMsg+0x2f406 0019ecc4 73d31a78 00000082 00000000 00000000 MFC42!CWnd::WindowProc+0x2207 0019ed24 73d319d0 00c3afc8 00000000 00000082 MFC42!AfxCallWndProc+0x9108 0019ed44 73dbe00c 00031002 00000082 00000000 MFC42!AfxWndProc+0x3409 0019ed70 76135cab 00031002 00000082 00000000 MFC42!AfxWndProcBase+0x390a 0019ed9c 761267bc 73dbdfd3 00031002 00000082 USER32!_InternalCallWinProc+0x2b0b 0019ee80 7612635a 73dbdfd3 00000000 00000082 USER32!UserCallWinProcCheckWow+0x3ac0c 0019eee4 76133f87 01225f90 00000000 00000082 USER32!DispatchClientMessage+0xea0d 0019ef28 77e62add 0019ef44 00000020 0019efac USER32!__fnNCDESTROY+0x370e 0019ef60 73d364c5 00031002 009a034c 009a1f14 ntdll!KiUserCallbackDispatcher+0x4d0f 0019ef74 00794760 009a8968 00000000 00c3afc8 MFC42!CWnd::DestroyWindow+0x3110 0019efb8 73d38fb4 00c3afc8 00c3afc8 00794965 JXC_MED!CMainFrame::DestroyWindow+0x13c [MainFrm.cpp @ 852] 11 0019efd0 02b056f3 00000000 00794a45 00c3afc8 MFC42!CFrameWnd::OnClose+0xf512 0019efec 007949a3 00000000 73dca64c 00000001 ToolLib!CTFrameWnd::OnClose+0x1313 0019f044 73d31e1d 00c3afc8 00c3afc8 00cae670 JXC_MED!CMainFrame::OnClose+0x3e [MainFrm.cpp @ 1133]
顶层两个函数调用帧都是错的,地址怪异 ,没有函数名子通过反汇编校验,根据帧返回地址是 0079451a 判断出具体函数源码位置,不及格的程序员-八神
JXC_MED!CMainFrame::`scalar deleting destructor":00794512 56 push esi00794513 8bf1 mov esi, this (ecx)00794515 e814000000 call JXC_MED!CMainFrame::~CMainFrame (79452e) //顶层栈实际上是在调用此析构函数中的代码0079451a f644240801 test byte ptr [esp+8], 10079451f 7407 je JXC_MED!CMainFrame::`scalar deleting destructor"+0x16 (794528)00794521 56 push esi00794522 e8338c0000 call JXC_MED!operator delete (79d15a)00794527 59 pop this (ecx)00794528 8bc6 mov eax, esi0079452a 5e pop esi0079452b c20400 ret 4JXC_MED!CMainFrame::~CMainFrame:0079452e b806828200 mov eax, 828206h00794533 e8489b0000 call JXC_MED!__EH_prolog (79e080)00794538 51 push this (ecx)00794539 51 push this (ecx)0079453a 56 push esi0079453b 8bf1 mov esi, this (ecx)0079453d 57 push edi0079453e 8975f0 mov dword ptr [ebp-10h], esi00794541 c70668a98800 mov dword ptr [esi], 88A968h00794547 8b8e58040000 mov this (ecx), dword ptr [esi+458h]0079454d c745fc06000000 mov dword ptr [ebp-4], 600794554 85c9 test this (ecx), this (ecx)00794556 7407 je JXC_MED!CMainFrame::~CMainFrame+0x31 (79455f)00794558 8b01 mov eax, dword ptr [this(??) (ecx)] //通过指令飞越技术查出是这里出错,代码对应 delete loadWareWork;0079455a 6a01 push 10079455c ff5004 call dword ptr [eax+4]0079455f a150889a00 mov eax, dword ptr ds:[009A8850h]00794564 83780400 cmp dword ptr [eax+4], 000794568 741f je JXC_MED!CMainFrame::~CMainFrame+0x5b (794589)00794623 c3 ret
CMainFrame::~CMainFrame(){ if(loadWareWork) delete loadWareWork; //这个被重复删了 导至出错 if (gpDb->IsOpen()) { WriteOpLog(gpDb, gstrOprCode, GSP_OPLOG_MODULEID, "2", "退出系统"); }}
图1:指令飞越技术重现@eip内存地址 0x8c73d01
解决办法,将这段代码删掉,此处多余的代码,理由是此类型是CWnd子类。不及格的程序员-八神创建时使用WS_CHILD类型创建,它会随着父窗体自动DESTORY, 并且子类重载函数 PostNcDestroy 并 delete this了,不需要这里再次delete。
关键词: