2015-09-18 11 views
11

इस 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 भेजना चाहते है।

enter image description here

मैं इस सवाल का जवाब इस 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_hWndNULL है ...

संपादित करें 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 माना जाता है, लेकिन यह नहीं है। जो दुर्घटना का कारण बनता है।

+0

'WM_SYSCOMMAND' को' SC_CLOSE' के wParam के साथ पोस्ट करने का प्रयास करें। –

+0

नहीं, ठीक उसी समस्या, 'pView-> m_hWnd' पहले से ही' NULL' है जब यह 'एएसएसईआरटी (:: IsWindow (pView-> m_hWnd)) हो जाता है;', वास्तव में यह 'CFormView' है, मैंने सवाल संपादित किया अगर यह कुछ भी बदलता है। – Smash

+0

इस बिंदु पर मैं कुछ ट्रेस स्टेटमेंट्स डालूंगा ताकि ऑर्डर प्राप्त हो सके जब आप "एक्स" स्वयं बनाम बनाते हैं जब आप 'WM_CLOSE' भेजते हैं। इससे प्रक्रिया पर कुछ प्रकाश डाला जाएगा। –

उत्तर

0

समस्या हल हो गई थी, समाधान के लिए प्रश्न में 3 संपादित करें देखें।

+1

उत्तर प्रश्न में नहीं होना चाहिए। – Mangs

1

ऐप को बंद करने के लिए ::PostQuitMessage(0); पर कॉल करें।

+0

यदि मैं आपके द्वारा सुझाए गए सुझावों का उपयोग करता हूं, तो व्युत्पन्न CFormViews के विनाशकों को कभी भी नहीं कहा जाता है ... – Smash

2

मुझे लगता है कि जिस तरह से आप फ्रेम बंद कर रहे हैं वह मुद्दा नहीं है। मेरा अनुमान है कि आप हाथों में से एक विचार को नष्ट कर देते हैं जबकि आपको उन्हें एमएफसी को हटा देना चाहिए (आपको शायद उनमें से एक पर DestroyWindow कहा जाता है)

संबंधित मुद्दे