इस stackoverflow प्रश्न के अनुसार:MFC CView (CFormView) विनाश दुर्घटना
What is the correct way to programmatically quit an MFC application?
मैं AfxGetMainWnd()->PostMessage(WM_CLOSE,0,0);
उपयोग कर रहा हूँ एक MFC कार्यक्रम बाहर निकलने के लिए। (एसडीआई, CFRameWnd जिसमें दो CFormViews के साथ एक CSplitterWnd है)
जैसा कि अपेक्षित है, यह DestroyWindow()
पर कॉल करता है।
समस्या का सामना करना पड़ रहा है कि व्युत्पन्न CFormView विनाश के बाद, के रूप में प्रति MSDN है:
एक गैर ऑटो सफाई वस्तु पर DestroyWindow कॉल करने के बाद, सी ++ वस्तु अभी भी चारों ओर हो जाएगा, लेकिन m_hWnd होगा शून्य हो। [MSDN]
अब CView
नाशक कहा जाता है और बिंदु पर
CDocument::RemoveView()...
CDocument::UpdateFrameCounts()
यह निम्नलिखित ज़ोर पर विफल रहता है: ASSERT(::IsWindow(pView->m_hWnd));
मैं जाँच की और m_hWnd
पहले से ही करने के लिए सेट कर दिया जाता बस से पहले कहा जाता व्युत्पन्न CView नाशक में शून्य।
क्या मैं गलत कर रहा हूँ?
संपादित करें:
यहाँ एक चार्ट को दर्शाता हुआ कारण है कि मैं एक WM_CLOSE संदेश और नहीं एक WM_QUIT भेजना चाहते है।
मैं इस सवाल का जवाब इस MSDN Technical Note में देता है लगता है, लेकिन मैं इसे समझ नहीं कर सकते हैं।
संपादित करें 2:
आदेश है कि चीजें कहा जाता हो: जो कहता है CWinApp::CloseAllDocuments(BOOL bEndSession);
1- AfxGetMainWnd()->PostMessage(WM_CLOSE,0,0);
2- Derived CFrameWnd::OnClose()
3- CFrameWnd::OnClose()
जो CDocManager::CloseAllDocuments(BOOL bEndSession)
जो
जो CDocument::OnCloseDocument()
कॉल अब कहता है, इस समारोह में कॉल
while (!m_viewList.IsEmpty())
{
// get frame attached to the view
CView* pView = (CView*)m_viewList.GetHead();
ASSERT_VALID(pView);
CFrameWnd* pFrame = pView->EnsureParentFrame();
// and close it
PreCloseFrame(pFrame);
pFrame->DestroyWindow();
// will destroy the view as well
}
तो हम देखते हैं कि CWnd::DestroyWindow()
कहा जाता है, तो:
4 - Derived CFormView destructor
5- CScrollView::~CScrollView()
6- CView::~CView()
जो CDocument::RemoveView(CView* pView)
जो CDocument::OnChangedViewList()
जो CDocument::UpdateFrameCounts()
कौन सा यहाँ दुर्घटनाओं कॉल कॉल कॉल: ASSERT(::IsWindow(pView->m_hWnd));
क्योंकि pView->m_hWnd
NULL
है ...
संपादित करें 3:
मैं पता लगा क्या समस्या थी:
पहली बार देखने के नाशक एक गैर-आरंभिकृत सूचक है, जो यूबी है को हटाने गया था। यह विनाशक लटका रहा था और कभी पूरा नहीं हुआ।
आमतौर पर, दूसरे दृश्य के विनाशक को केवल पहले के पूरा होने पर ही बुलाया जाता है। लेकिन इस मामले में इसे अभी भी निष्पादित किया जा रहा था हालांकि पहला व्यक्ति कभी पूरा नहीं हुआ।
के बाद से पहली बार देखने आधार वर्ग विनाशकर्ता कभी नहीं कहा जाता था, इस समारोह कभी नहीं पहली बार देखने के लिए बुलाया गया था:
void CDocument::RemoveView(CView* pView)
{
ASSERT_VALID(pView);
ASSERT(pView->m_pDocument == this); // must be attached to us
m_viewList.RemoveAt(m_viewList.Find(pView));
pView->m_pDocument = NULL;
OnChangedViewList(); // must be the last thing done to the document
}
कहाँ हम देख सकते हैं कि दृश्य m_viewList
से हटा दिया है।
इसका मतलब यह है कि जब दूसरे दृश्य नाशक पूरा करता है, में:
void CDocument::UpdateFrameCounts()
// assumes 1 doc per frame
{
// walk all frames of views (mark and sweep approach)
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
...
स्थिति NULL
माना जाता है, लेकिन यह नहीं है। जो दुर्घटना का कारण बनता है।
'WM_SYSCOMMAND' को' SC_CLOSE' के wParam के साथ पोस्ट करने का प्रयास करें। –
नहीं, ठीक उसी समस्या, 'pView-> m_hWnd' पहले से ही' NULL' है जब यह 'एएसएसईआरटी (:: IsWindow (pView-> m_hWnd)) हो जाता है;', वास्तव में यह 'CFormView' है, मैंने सवाल संपादित किया अगर यह कुछ भी बदलता है। – Smash
इस बिंदु पर मैं कुछ ट्रेस स्टेटमेंट्स डालूंगा ताकि ऑर्डर प्राप्त हो सके जब आप "एक्स" स्वयं बनाम बनाते हैं जब आप 'WM_CLOSE' भेजते हैं। इससे प्रक्रिया पर कुछ प्रकाश डाला जाएगा। –