Я работаю над приложением mfc для встроенного компакт-диска. На данный момент я пытаюсь добавить диалог, который предлагает закрыть программу. Моя проблема в том, что я получаю нарушение доступа при вызове деструктора из моего CMainFrame. Чтобы сделать его более понятным, сначала кусок кода. Это начальная точка моего приложения:Нарушение прав доступа при вызове деструктора из CMainFrame после завершения приложения mfc
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;
}
Но нарушение еще occurres ... я искал CallStack окно, но не мог найти его на вкладке Вида ... Sry для этого длинного поста! И, если это слишком специфично ... Но я боюсь с тех пор, как несколько часов и не знаю, что я могу попробовать ... Любая помощь приветствуется!
Dont делать AfxGetApp() -> m_pMainWnd = NULL; Структура делает это за вас. –
Можете ли вы запустить его в режиме отладки, чтобы увидеть, где он сбой? –
Попробуйте изменить AfxGetMainWnd() -> PostMessage (WM_CLOSE); to :: PostQuitMessage (0); –