【发布时间】:2015-05-29 00:24:59
【问题描述】:
我正在为嵌入式紧凑型开发一个 mfc 应用程序。目前我尝试添加一个对话框,提供关闭程序。我的问题是我在 CMainFrame 的析构函数调用中遇到访问冲突。 为了更清楚,首先一段代码。 这是我的应用程序的起点:
SWinApp.h
class SWinApp : public CWinApp
{
public:
SWinApp();
~SWinApp(){};
public:
virtual BOOL InitInstance();
protected:
DECLARE_MESSAGE_MAP()
};
SWinApp.cpp
SWinApp::SWinApp():CWinApp()
{
}
BOOL SWinApp::InitInstance()
{
CRuntimeClass* pRuntimeClass = RUNTIME_CLASS( SMainFrame );
CObject* pObject = pRuntimeClass->CreateObject();
ASSERT( pObject->IsKindOf( RUNTIME_CLASS( SMainFrame ) ) );
m_pMainWnd = (SMainFrame*)pObject;
m_pMainWnd->ShowWindow(SW_SHOWMAXIMIZED);
return FALSE; // this is the next executed line after the access violation
}
BEGIN_MESSAGE_MAP(SWinApp, CWinApp)
END_MESSAGE_MAP()
SMainFrame.h
class SMainFrame : public CFrameWnd
{
DECLARE_DYNCREATE(SMainFrame)
protected:
SMainFrame();
~SMainFrame();
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
afx_msg LRESULT OnDialogReady(WPARAM wParam, LPARAM lParam);
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
CurrentData* GetCurrentData(){return this->currentData;};
Configuration* GetConfiguration(){return this->configuration;};
private:
BOOL m_shown;
CurrentData* currentData;
Configuration* configuration;
std::map<UINT, CDialog*> views;
UINT currentID;
};
SMainFrame.cpp
IMPLEMENT_DYNCREATE(SMainFrame, CFrameWnd)
SMainFrame::SMainFrame()
{
CString appName;
appName.LoadStringW(IDS_APP_NAME);
Create(NULL, appName);
m_shown = FALSE;
this->configuration = new Configuration();
this->currentData = new CurrentData();
this->currentID = IDD_MAIN_MENU_DIALOG;
views.insert(std::make_pair(IDD_MAIN_MENU_DIALOG, new MainMenuDialog(this->configuration, this->currentData)));
// There are more dialogs but for tests one is enough
}
SMainFrame::~SMainFrame()
{
for(auto iterator:views)
{
delete iterator.second;
}
delete this->configuration;
delete this->currentData; //Is executed properly
} // After this line an access violation occurres...
BEGIN_MESSAGE_MAP(SMainFrame, CFrameWnd)
ON_MESSAGE(WM_USER_DIALOG_READY, &SMainFrame::OnDialogReady)
ON_WM_CREATE()
ON_WM_ACTIVATE()
END_MESSAGE_MAP()
// SMainFrame message handlers
int SMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
ModifyStyle(WS_CAPTION, 0, SWP_DRAWFRAME | SWP_NOZORDER );
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
afx_msg LRESULT SMainFrame::OnDialogReady(WPARAM wParam, LPARAM lParam)
{
DialogThreadParams* params = (DialogThreadParams*)lParam;
this->currentID = params->nextDialogID;
m_shown = FALSE;
this->ActivateFrame();
return 0;
}
BOOL SMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE | SWP_DRAWFRAME;
cs.style = WS_EX_CLIENTEDGE;
return TRUE;
}
void SMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
if(m_shown == FALSE)
{
m_shown = TRUE;
if(IsWindow(views[currentID]->m_hWnd))
{
views[currentID]->SetFocus();
}
else
{
views[currentID]->DoModal();
}
}
CFrameWnd::OnActivate(nState, pWndOther, bMinimized);
}
MainMenuDialog是继承自StandardDialog的类,继承自CDialog。我现在只发布部分代码,因为这篇文章已经太长了(如果您需要更多,请告诉我哪个部分可能很有趣)...... 提供关闭应用程序可能性的对话框称为 ShutdownDialog(仅继承自 CDialog),并存储为 MainMenuDialog 的私有变量:
ShutdownDialog* shutdownDialog;
在 MainMenuDialog 的构造函数中创建:
this->shutdownDialog = new ShutdownDialog();
我在单击按钮时显示对话框:
void MainMenuDialog::OnClickedShutdownButton()
{
shutdownDialog->DoModal();
}
并在MainMenuDialog的析构函数中被删除:
MainMenuDialog::~MainMenuDialog()
{
delete shutdownDialog;
}
在 ShutdowDialog 中,我使用这段代码关闭应用程序:
AfxGetMainWnd()->PostMessage(WM_CLOSE);
EndDialog( 0 );
在此之前一切正常。应用程序开始销毁对象。但是在完成对 SMainFrame 析构函数的调用后,我遇到了访问冲突。程序不会停止,只是输出窗口中的一行。它继续声明“return FALSE;”在 SWinApp InitInstance() 中。
我知道在删除对象两次或使用依赖对象已被破坏的指针时会发生访问冲突,但我无法弄清楚这里出了什么问题。另外我不得不说 SWinApp 和 SMainFrame 是由一位同事创建的,我使用 SMainFrame 中的对话框修改了这些部分。 我认为 m_pMainWnd 可能是问题所在,因为在对 SMainFrame 的析构函数调用之后,它必须是一个无效的指针。所以我尝试了:
SMainFrame::~SMainFrame()
{
for(auto iterator:views)
{
delete iterator.second;
}
delete this->configuration;
delete this->currentData;
AfxGetApp()->m_pMainWnd = NULL;
}
但是违规仍然发生... 我搜索了调用堆栈窗口,但在视图选项卡下找不到它... 为这篇长篇文章感到抱歉! 对不起,如果这太具体了...但是我已经挣扎了几个小时,不知道我可以尝试什么...欢迎任何帮助!
【问题讨论】:
-
不要做 AfxGetApp()->m_pMainWnd = NULL;该框架为您完成。
-
您可以在调试模式下运行它以查看它崩溃的确切位置吗?
-
尝试更改 AfxGetMainWnd()->PostMessage(WM_CLOSE);到::PostQuitMessage(0);
-
@Andrew Komiagin:非常感谢! PostQuitMessage 解决了我的问题:) 如果您再次将其发布为 answear,我将接受它。现在我只收到一条消息:警告:正在销毁非 NULL m_pMainWnd。但我读到的是,这不是错误,只是信息:)
标签: c++ mfc destructor access-violation