Release版VC6 MFC程序 程序正常退出时得到一个如下异常调用栈:

0:000>kb
# ChildEBP RetAddr Args to Child
WARNING: Frame IP not
inany known module. Following frames may be wrong.00 0019eb94 76124f2f 00c3afc8 0019ebdc 0019ebb8 0x8c73d01 01 0019ebdc 0079451a 00c3afc8 73d82ec0 00000001 USER32!IsZoomed+0xaf 02 0019ebe4 73d82ec0 00000001 73d35d1c 00c3afc8 JXC_MED!CMainFrame::`scalar deleting destructor'+0x8 03 0019ebec 73d35d1c 00c3afc8 00000000 73d35c0f MFC42!CControlFrameWnd::PostNcDestroy+0xb 04 0019ec2c 73d31e1d 00c3afc8 00c3afc8 00cae670 MFC42!CWnd::OnNcDestroy+0x10d 05 0019eca4 73d31b07 00000082 00000000 73dca448 MFC42!CWnd::OnWndMsg+0x2f4 06 0019ecc4 73d31a78 00000082 00000000 00000000 MFC42!CWnd::WindowProc+0x22 07 0019ed24 73d319d0 00c3afc8 00000000 00000082 MFC42!AfxCallWndProc+0x91 08 0019ed44 73dbe00c 00031002 00000082 00000000 MFC42!AfxWndProc+0x34 09 0019ed70 76135cab 00031002 00000082 00000000 MFC42!AfxWndProcBase+0x390a 0019ed9c 761267bc 73dbdfd300031002 00000082 USER32!_InternalCallWinProc+0x2b0b 0019ee80 7612635a 73dbdfd300000000 00000082 USER32!UserCallWinProcCheckWow+0x3ac0c 0019eee4 76133f87 01225f9000000000 00000082 USER32!DispatchClientMessage+0xea0d 0019ef28 77e62add 0019ef4400000020 0019efac USER32!__fnNCDESTROY+0x370e 0019ef60 73d364c500031002 009a034c 009a1f14 ntdll!KiUserCallbackDispatcher+0x4d0f 0019ef7400794760 009a8968 00000000 00c3afc8 MFC42!CWnd::DestroyWindow+0x31 10 0019efb8 73d38fb4 00c3afc8 00c3afc8 00794965 JXC_MED!CMainFrame::DestroyWindow+0x13c [MainFrm.cpp @ 852]11 0019efd0 02b056f3 00000000 00794a45 00c3afc8 MFC42!CFrameWnd::OnClose+0xf5 12 0019efec 007949a3 00000000 73dca64c 00000001 ToolLib!CTFrameWnd::OnClose+0x13 13 0019f044 73d31e1d 00c3afc8 00c3afc8 00cae670 JXC_MED!CMainFrame::OnClose+0x3e [MainFrm.cpp @ 1133]

顶层两个函数调用帧都是错的,地址怪异 ,没有函数名子通过反汇编校验,根据帧返回地址是
0079451a
判断出具体函数源码位置,
不及格的程序员-八神

JXC_MED!CMainFrame::`scalar deleting destructor':
00794512 56push    esi00794513 8bf1           mov     esi, this(ecx)00794515 e814000000     call    JXC_MED!CMainFrame::~CMainFrame (79452e) //顶层栈实际上是在调用此析构函数中的代码
0079451a f644240801 test
byte ptr [esp+8], 10079451f7407 je JXC_MED!CMainFrame::`scalar deleting destructor'+0x16 (794528) 00794521 56push esi00794522 e8338c0000 call JXC_MED!operator delete(79d15a)00794527 59 pop this(ecx)007945288bc6 mov eax, esi
0079452a 5e pop esi
0079452b c20400 ret
4JXC_MED!CMainFrame::~CMainFrame:
0079452e b806828200 mov eax, 828206h
00794533 e8489b0000 call JXC_MED!__EH_prolog (79e080)00794538 51 push this(ecx)00794539 51 push this(ecx)
0079453a
56push esi
0079453b 8bf1 mov esi,
this(ecx)
0079453d
57push edi
0079453e 8975f0 mov dword ptr [ebp
-10h], esi00794541c70668a98800 mov dword ptr [esi], 88A968h00794547 8b8e58040000 mov this (ecx), dword ptr [esi+458h]
0079454d c745fc06000000 mov dword ptr [ebp
-4], 6 00794554 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], 0 00794568 741f je JXC_MED!CMainFrame::~CMainFrame+0x5b (794589)
00794623 c3 ret
CMainFrame::~CMainFrame()
{
if(loadWareWork) deleteloadWareWork; //这个被重复删了 导至出错if (gpDb->IsOpen())
{
WriteOpLog(gpDb, gstrOprCode, GSP_OPLOG_MODULEID, "2", "退出系统");
}
}

在内存窗口中查看此变量周围已经被16进制 feee feee填充,看我博文
Microsoft平台开发,内存特征码识别
有讲述通过16进制分辨内存数据,说明此内存区已经被heap free.

图1:指令飞越技术重现@eip内存地址
0x8c73d01

解决办法,将这段代码删掉,此处多余的代码,理由是此类型是CWnd子类。
不及格的程序员-八神
创建时使用WS_CHILD类型创建,它会随着父窗体自动DESTORY, 并且子类重载函数 PostNcDestroy 并 delete this了,不需要这里再次delete。

标签: none

添加新评论