首页
社区
课程
招聘
new一个MFC窗口类,delete时报异常
发表于: 2012-9-12 01:35 9856

new一个MFC窗口类,delete时报异常

2012-9-12 01:35
9856
通过键盘钩子注入dll到进程1,然后在按键回调函数中new一个MFC自定义窗口类
代码如下:
pMainForm = new CMainForm(); //创建主窗口类
		if (pMainForm->Create(IDD_DLG_MAIN, NULL) == FALSE)
		{
			delete pMainForm;
			pMainForm = NULL;
			return;
		}

		pMainForm->ShowWindow(SW_SHOW); //显示窗口

在释放的窗口的时候,调用delete MFC类对象,就报异常.
if (pMainForm)
			{
				//::DestroyWindow(pMainForm->m_hWnd); //MSDN:A thread cannot use DestroyWindow to destroy a window created by a different thread. 
				//pMainForm->DestroyWindow(); //--调用这个报错,只能在创建窗口的线程中调用
				//SendMessage(pMainForm->m_hWnd, WM_DESTROY, NULL, NULL);
				//_asm int 3
				delete pMainForm; //调用这个会异常
				pMainForm = NULL;
			}

异常时,OD代码:
  PUSH    EDI
  PUSH    0
  CALL    MFC42.#6581
  PUSH    DWORD PTR [ESI+20]
  MOV     ECX, EAX //EAX=0,异常开始了
  CALL    MFC42.#3848
  CMP     DWORD PTR [ESI+3C], 0
  MOV     EBX, EAX
  JNZ     SHORT MFC42.0AD56463
  PUSH    DWORD PTR [ESI+20]
  CALL DestroyWindow
  JMP     SHORT MFC42.0AD5646B

可以肯定的是这里已经是析构函数,但还没到DestroyWindow
至于 CALL    MFC42.#6581,CALL    MFC42.#3848
这两个call是干什么的,能力有限,暂时还分析不出来?---如何分析,还请高人指点
我估计错误跟MFC窗口类本身定义有关,我的类里头一个句柄都没

 
class CMainForm : public CDialog
{
// Construction
public:
	CMainForm(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{{AFX_DATA(CMainForm)
	enum { IDD = IDD_DLG_MAIN };
	CTabCtrl	m_MainTab;
	//}}AFX_DATA


// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMainForm)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:

	// Generated message map functions
	//{{AFX_MSG(CMainForm)
	virtual BOOL OnInitDialog();
	afx_msg void OnSelchangeMainTab(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnDestroy();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 142
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我觉得很大可能是pMainForm没有创建成功
pMainForm使用之前先初始化一下
pMainForm = NULL;
再去
pMainForm = new CMainForm();
否则你这行代码
if (pMainForm)可能会出问题,比如pMainForm根本没创建成功,但是if (pMainForm)仍然成立,delete一个不存在的对象,后果是什么.

额,忘了问了,窗口已经出来了么,要是出来了那我上面的话作废
2012-9-12 02:13
0
雪    币: 126
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
窗口已经出来了
经过调试测试,找到问题出错地方及原因:
上面OD代码就是下面的MFC源码:
BOOL CWnd::DestroyWindow()
{
	if (m_hWnd == NULL)
		return FALSE;

	CHandleMap* pMap = afxMapHWND(); //错误就是这里找不到handle
	ASSERT(pMap != NULL);
	CWnd* pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);
#ifdef _DEBUG
	HWND hWndOrig = m_hWnd;
#endif

#ifdef _AFX_NO_OCC_SUPPORT
	BOOL bResult = ::DestroyWindow(m_hWnd);
#else //_AFX_NO_OCC_SUPPORT
	BOOL bResult;
	if (m_pCtrlSite == NULL)
		bResult = ::DestroyWindow(m_hWnd);
	else
		bResult = m_pCtrlSite->DestroyControl();
#endif //_AFX_NO_OCC_SUPPORT
...

CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
{
	AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); //看这个名字,好像是跟线程有关的
	if (pState->m_pmapHWND == NULL && bCreate)
	{
		BOOL bEnable = AfxEnableMemoryTracking(FALSE);
#ifndef _AFX_PORTABLE
		_PNH pnhOldHandler = AfxSetNewHandler(&AfxCriticalNewHandler);
#endif
		pState->m_pmapHWND = new CHandleMap(RUNTIME_CLASS(CTempWnd),
			offsetof(CWnd, m_hWnd));

#ifndef _AFX_PORTABLE
		AfxSetNewHandler(pnhOldHandler);
#endif
		AfxEnableMemoryTracking(bEnable);
	}
	return pState->m_pmapHWND;
}

我之前的new和delete的代码不是在一个线程的,改成一个线程上操作时就不会报错.

请问高人,能不能在不同线程new/delete一个mfc窗口???
2012-9-12 03:59
0
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
你这个压根就是设计滴有问题。在一个线程中创建的窗体,理应在这个窗体释放。在另一个线程感知到这个窗体需要释放的情况下,你可以通过发送消息等方式通知创建窗体的线程对窗体进行销毁。至于你想再另一个线程中操作这个窗体,感觉理论上应该可以。期待大牛。。。(虽然这么做设计上很有问题)
2012-10-18 11:00
0
雪    币: 31
活跃值: (53)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
应该不可以吧,毕竟消息都是基于线程的,你GetLastError下看。
2012-10-18 11:09
0
雪    币: 244
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我尽然看完了所有的内容
2016-3-24 10:21
0
游客
登录 | 注册 方可回帖
返回
//