1. 程式人生 > >知識點:吐槽Win7專業版和Win7旗艦版對C++/程式的影響

知識點:吐槽Win7專業版和Win7旗艦版對C++/程式的影響

今天遇到了一個很奇怪的問題,我的電腦是win7+64專業版的,在VC6.0上除錯MFC程式,最後程式關閉的時候,彈出下述警告
在這裡插入圖片描述
但是在Release版本不會出現這個問題,最關鍵的是在同學電腦(Win7+64旗艦版)無論是Debug還是Release都沒問題,弄得我差點重灌系統。
後來,進入提示中的filecore.cpp(這是VC6.0軟體自己的檔案)的295行,程式如下

void CFile::Close()
{
	ASSERT_VALID(this);
	ASSERT(m_hFile != (UINT)hFileNull);//這裡報錯了
	BOOL bError = FALSE;
	if (m_hFile != (UINT)hFileNull)
		bError = !::CloseHandle((HANDLE)m_hFile);
	m_hFile = (UINT) hFileNull;
	m_bCloseOnDelete = FALSE;
	m_strFileName.Empty();
	if (bError)
		CFileException::ThrowOsError((LONG)::GetLastError());
}

大意就是說,這個要關閉的檔案控制代碼不能為空,否則報錯。

CGraphicDoc::~CGraphicDoc()
{
	delete m_UndoList;
	Fundo.Close ();//這裡Fundo不能為空,也就說不能是無效變數
	remove(FileName);
}

Release對野指標之類的要求是比Dubug要低的,至於為什麼WIn7旗艦版也能允許,是因為專業版對程式的要求更嚴格了。比如看一下下邊這個問題

void CMyBitmap::make_palette (int a)
{
		if(a==0){	
			GlobalFreePtr(cp);//全域性釋放cp的控制代碼,cp型別為LPLOGPALETTE*
		}
		GlobalFreePtr(cp);//win7專業版會報錯,win7旗艦版不會報錯
}

可以看到:當a為0的時候,執行了兩遍GlobalFreePtr(cp);如果在Win7旗艦版上,函式是可以正常執行的,但是Win7專業版上就不行,第一次執行GlobalFreePtr(cp)後,cp是已經釋放過了,第二次釋放的時候,Winodws會認為是野指標了,專業版會報錯的,但是旗艦版不知是規避了還是沒有處理方正是函式正常退出了。
而解決方法很簡單,上述程式碼只要加上一個else就可以了

void CMyBitmap::make_palette (int a)
{
		if(a==0){	
			GlobalFreePtr(cp);//全域性釋放cp的控制代碼,cp型別為LPLOGPALETTE*
		}
		else	//保證GlobalFreePtr只執行一遍
			GlobalFreePtr(cp);
}

所以如果大家發現在Win7專業版系統上,經常出現某些程式已停止工作,並不是系統缺東西,而是軟體寫的不夠好(比如說我的有道雲筆記經常提示我“您的有道雲筆記已停止工作~~~~~~~~”)

補充一個MFC框架的知識點:MFC框架程式的退出主要是doc、view、frame的退出,也就是這三個類呼叫各自的解構函式,而呼叫的順序依次為:~ Frame()、~ View()、~ doc()。如果退出的時候,就依照這個順序加斷點除錯就可以了。
最後吐槽一下VC6.0:加斷點除錯的時候,按F10一步一步的走,如果此時進入的程式對應的.cpp檔案沒有在工作空間中開啟,那麼它就會進入彙編的頁面,而不是在編輯器中開啟相應cpp檔案在其中顯示,但是從VS2010以上的版本就可以自動開啟cpp檔案。當VC6.0中出現這樣的情況時,可以在除錯過程中,在彙編頁面加斷點,然後停止除錯執行後,按ctr+B去找加斷點的位置。這也算除錯老程式的無奈之舉了。