2011-01-07 144 views
2

我在MFC/c + +中做了一個簡單的應用程序。這段代碼是在CWinApp類中創建一個對話框。它編譯得很好,運行也很好,但是隻有當我從VStudio運行它時,如果我運行它直接導致運行時錯誤,程序崩潰。奇怪的問題MFC C++

CMyDialog dlg; 
m_pMainWnd = (CWnd*)&dlg; 
dlg.DoModal(); 

但如果我使用下面的代碼,那麼一切都很好。我不明白這種行爲。

CMyDialog *dlg=new CMyDialog(); 
m_pMainWnd = (CWnd*)dlg; 
dlg->DoModal(); 

這種類型的事情以前也發生過很多次,對於我以前的其他一些C++(非MFC)項目。 請給我指定。

+0

當問題發生時,您可以從第一個案例發佈調用堆棧嗎? – 2011-01-07 14:37:40

+1

我其實已經理解了這個問題,但是這裏是調用堆棧(僅在發佈模式下出錯)。 > \t NTDLL.DLL!7c911e58()\t \t [下面的幀可能是不正確的和/或缺失,沒有加載ntdll.dll的符號] \t \t NTDLL.DLL!7c918251()\t \t NTDLL.DLL!7c911c76 ()\t \t ntdll.dll中!7c911538()\t \t ntdll.dll中!7c9106eb()\t \t ntdll.dll中!7c9140bb()\t KERNEL32.DLL \t!7c801a4f()\t \t ntdll.dll中!7c90e234()\t KERNEL32.DLL \t!7c8110db()\t KERNEL32.DLL \t!7c801a24()\t \t ...等也只是註釋大小StackOverflow的溢出 \t ... – YAHOOOOO 2011-01-07 14:44:21

+0

在這種情況下,我通常在崩潰後立即選擇「調試」。假設Visual Studio以DEBUG版本打開,即使您雙擊可執行文件,仍然可以在崩潰後調試程序並找到問題的底部。 – 2017-04-04 08:57:14

回答

2

在第一種情況下,對象被銷燬(當dlg超出範圍時),但仍由m_pMainWnd指向。有可能/有可能​​會導致使用m_pMainWnd並訪問不再存在的對象。

變化的第一個例子:

CMyDialog dlg; 
m_pMainWnd = (CWnd*)&dlg; 
dlg.DoModal(); 
m_pMainWnd = NULL; 

如果解決了這個問題,你在第二種情況下逃脫了它的原因是對象沒有被銷燬(儘管因爲m_pMainWnd指向它,MFC可能會在程序關閉時爲您破壞;確實,這可能是另一種情況下崩潰的根源)。

1

這兩個代碼塊之間的主要區別在於第一個dlg將在塊的末尾被銷燬,第二個在這裏的任何代碼中都不會銷燬。

鑑於你的程序的其餘部分,dlg仍然需要在它聲明的塊的末尾?如果是這樣,你需要使用類似第二塊的東西。

或者,有可能DoModal調用delete(this)(直接或間接) - 在這種情況下,dlg必須使用new

1

的問題是,你設置m_pMainWnd時關閉對話框,不會存在了一個窗口,該之前通常發生對話框破壞,只是當你關閉對話框(在DoModal返回時)。

我解決了這個問題,通過創建一個虛擬窗口,並把它作爲主窗口:

class CDummyWindow : public CFrameWnd 
{ 
public: 
    CDummyWindow() 
    { 
     Create(NULL, NULL); 
    } 
}; 

Class::InitInstance() 
{ 
    ... 
    CDummyWindow win; 
    m_pMainWnd = &win; 
    ... 
    return FALSE; 
} 

要確保你return FALSE表明該應用程序應該停止。