今天在將2003建立的工程轉換成2005時,發現遇到很多問題,網上搜了一些解決辦法:
經常寫VC工程的人都會遇到升級到VS2005時出現的各種各樣的問題,下面寫一些自己遇到的問題,還有什麼不全的請大家補充。希望能給朋友們一些幫助。
VC6 和 VS2003 轉換到VS2005 時可能會遇到的問題以及解決方法
1.以前可以這樣用try catch
catch(CException *e)
{
pApp->Warn("%s",e->GetErrorMessage);
e->Delete();
return FALSE;
}
現在必須修改爲:
catch(CException *e)
{
TCHAR errormsg[255];
e->GetErrorMessage (errormsg,255,NULL);
pApp->Warn("%s",errormsg);
e->Delete();
return FALSE;
}
2. strchr必須強制轉換一下。
以前可以 char *str2=strchr(line,'|');
2005必須 char *str2=(char *)strchr(line,'|');
3.lifescope of int i in for(int i; i< size; ++i)in VC6,
the codes below are ok
for(int i = 0; i< 10; ++i)
{
//...
}
for(i = 20; i< 40;++i)
{
//...
}
but in VS2005, we should write like below:
for(int i = 0; i< 10; ++i)
{
//...
}
for(int i = 20; i< 40;++i)
{
//...
}
in fact, from vs.net, the compiler accord with C++ standard more than VC6.
If you are porting a VC6 project to VS2005, you will encounter many many codes like this.
4. ON_WM_NCHITTEST (and other MFC macros) won't compile in VS2005
VS2005中,ON_WM_NCHITTEST宏編譯不過
When I add a message handler of ON_WM_NCHITTEST to a CControlbar-derived class, it compiles error:
error C2440: 'static_cast' : cannot convert from 'UINT (__thiscall CMenuBar::* )(CPoint)' to 'LRESULT (__thiscall CWnd::* )(CPoint)' Cast from base to derived requires dynamic_cast or static_cast
To fix this bug, we should change the prototype of OnNcHitTest
from
afx_msg UINT OnNcHitTest(CPoint point);
to
afx_msg LRESULT OnNcHitTest(CPoint point);
5. VS2005中有些可能引起內存越界的函數不建議使用了
In VS2005, some dangerous functions are deprecated
char c[10];
strcpy(c, "testtestts"); //ok with VC6, but not in VS2005
strcpy_s(c, _countof(c),"testtestt");//9 chars, ok in VS2005
strcpy_s(c, _countof(c),"testtestt");//10 chars, assert!!!!! in VS2005
6.
error C2440: 'static_cast' : cannot convert from 'HRESULT (__thiscall CtestpalView::* )(WPARAM,LPARAM)' to 'AFX_PMSG'
None of the functions with this name in scope match the target type
HRESULT (__thiscall CtestpalView::* )(WPARAM,LPARAM)
AFX_PMSG類型:
void (AFX_MSG_CALL CCmdTarget::* )(void)
7.
error C2440: 'static_cast' : cannot convert from 'void (__thiscall CSettingStart::* )(BOOL,HANDLE)' to 'void (__thiscall CWnd::* )(BOOL,DWORD)'
In VC6, the handler for ON_WM_ACTIVATEAPP was expected to be
afx_msg void OnActivateApp( BOOL, HANDLE);
In VC7 and vs2005, it has been changed to
afx_msg void OnActivateApp( BOOL, DWORD );
8.
error LNK2019: unresolved external symbol "wchar_t * __stdcall _com_util::Co.....
解決方法,
Property page ->C/C++ ->Language ->treat Wchar-t 改爲 No
未完待續......
官方總結:
Visual C++ 2005庫已經發生了一系列的變化,可能會對現有的程序有所影響,在升級到Visual C++ 2005之前,必須要確定程序中沒有這些問題。
1、參數的有效性
在C運行時庫中,加入了一些代碼,以檢查參數的有效性。例如:如果傳遞的目標緩衝區大小不足以strcpy使用--通常這是在冒安全風險,而新版本此時則會調用一個非法參數處理程序。在release版中,會調用Dr.Watson;而在debug版中,會產生斷言(assert),當然,只要程序中傳遞的參數都是有效的,就不會有什麼問題了。
2、對非安全API的警告
在Visual C++ 2005中,CRT中的一組函數已不再建議使用,而應使用新提供的安全版本。大多數這些不建議使用的函數如果使用不當,將會導致緩衝區溢出或其他安全問題,這些函數如:strcpy、strcat等等。這些函數新的安全版本都在函數名後加了一個_s後綴,以方便識別,如strcpy_s、wcscpy_s、mbscpy_s、calloc_s和strcat_s這些函數。
如果想繼續使用老版本、非安全的函數,可在源代碼開始處加上#define value of _CRT_SECURE_NO_DEPRECATE(此處value代表某一數值);然而,還是建議大家升級代碼使用新的安全函數。
3、迭代器越界
受檢查的迭代器(checked iterators)和調試迭代器(debug iterators)也因爲安全的原因進行了相應的更新,如果迭代器越界,則相應會調用一個非法參數處理程序。
再次提醒,可以通過拋出一個越界異常來避免產生非法參數問題。在代碼中加入#define value of _SECURE_SCL_THROWS,並把value值設爲1,這樣就不會調用非法參數處理程序,而是產生一個異常了。
也可以通過設置#defined value of _SECURE_SCL值爲零,關閉此迭代器檢查,通常默認情況下,此選項是打開的。
4、time_t類型
time_t類型通常用於顯示從1970年開始以來的秒數。直到Visual C++ 7.1(即Visual C++ .net 2003),time_t類型都被定義爲一個long,而到了Visual C++ 2005中,已被定義爲一個64位類型,可用於顯示一直到3000年的時間了。
5、鏈接到CRT
託管應用程序現在不能靜態鏈接到CRT。以往,在Visual C++ 7.0和7.1中(指Visual Studio .NET 2002與2003),可以生成靜態鏈接到CRT的CLR程序,而在Visual Studio 2005卻行不通。
6、單線程CRT支持
在Visual Studio 2005中,已經取消了單線程CRT支持。而且用發展的眼光來看,未來大多數的人還是願意使用線程安全的多線程代碼。
在線程中,可使用_nolock後綴來優化代碼,但同時,這些函數是非線程安全的。
7、異常處理
有兩種類型的異常處理可供選擇:/EHa(異步的)和/EHs(同步C++異常)。在以前,如果使用了/EHs,那麼在一個catch(…)塊中,也許可能、也許不可能捕捉到結構化異常,因爲此行爲是沒有定義且不可靠的;現在,再使用/EHs時,就可保證不會捕捉到結構化異常。如果想與以前版本的Visual C++保持一致,並且捕捉異步結構化異常,還是應該在編譯時使用/EHa。
8、初始化順序
以往,如果代碼中同時有託管與本地全局變量及對象,那麼初始化順序是不確定的;如代碼中存在託管對象與本地對象互操作,就不能保證哪一個對象先初始化了。現在,Visual Stuio 2005可保證所有的本地全局變量及對象先初始化,然後才初始化託管全局變量及對象。
9、printf
就目前來說,printf中的%n格式化指示符一般用於指定輸出的字符個數。這已經確認爲一個安全隱患,並且已禁用,但可以使用set_printf_count_output來啓用它;通過傳遞給set_printf_count_output一個零值(0)可禁用它,而傳遞任意一個其他值可再次啓用。
10、swprintf函數
爲與C++標準保持一致,對swprintf函數也作了修改,現在它已遵循C++標準了。在C++中,通過適當的參數,可實現重載;這個函數的老版本已不再建議使用,因爲在C中,是不允許重載的,因此如果使用老格式,將會返回一個錯誤。編譯器中的突破性變化
除了那些會影響到庫的變化之外,也有一些變化會影響到編譯器。以下是Visual C++ 2005中編譯器的主要變化,需再次提醒的是,此處並沒有列出所有的變化,但卻是微軟公司VC++使用者及內部合作者所確認的關鍵性變化。
指向成員的指針
在之前的版本中,一個指向成員的指針不需使用取址操作符(&)就能獲取,現在,Visual C++ 2005已經嚴格按照標準,必須要使用取址操作符,這也有助於消除潛在的運行時錯誤。但也導致了MFC庫的許多地方需要修改,同時意味着,可能會對現有的程序造成影響。
範圍限制規則
在for循環聲明中,默認情況下不強制執行範圍限制規則。在之前的版本中,for循環中變量的生命期將會延續到循環之外,爲與標準兼容,for循環中定義的變量,現在只限定在for循環內使用。
wchar_t類型
現在,wchar_t已爲默認內置類型。這就是說,也許在以前,wchar_t可能會被當作一個unsigned short,因爲它還不是內置類型,所以,當與那些有wchar_t類型變量的文件作符號比較時,很可能會導致問題。在Visual C++ 2005中,wchar_t已是一個內置類型,也就是說,需要確定以前對wchar_t的用法不會導致轉譯爲一個unsigned short。
異常處理
爲了與庫的變化保持一致,編譯器已作了一些修改,以便不會捕捉到結構化異常。所以,爲與以前代碼保持兼容,還是應該使用/EHa。
參數屬性
爲了提供更健壯的屬性--也是爲了代碼的健壯性,編譯器現在將會檢查類型、枚舉等等的屬性。這意味着,以前的代碼可能會在屬性方面碰到一個從未有過的編譯器錯誤。
默認爲int
爲遵循C++標準,對沒有類型聲明的變量或函數,已不再默認爲int類型。但在C語言中仍然可以,C++語言中已不行。這甚至也影響到了微軟公司自身的代碼,包括NT系統的代碼,所以最好的方式,還是顯式聲明。
關於C的託管代碼
C語言編譯器一般不可能創建CLR的託管代碼,因爲C語言不是面向對象的,它不符合CLR所使用的模型,因此,任何以C語言來編譯的代碼都會與CLR編譯器設置衝突。例如,如果在編譯時使用/TC設置,而且又設置了CLR,就會導致衝突。
面向CLR的新語法
通過設置/clr編譯選項,C++編譯器只接受新語法。這將強制推廣加入到Visual C++ 2005中的新語法,同時,也會廢棄掉老代碼。
安全檢查
在安全越來越得到重視的今天,安全檢查選項/GS,在默認情況下就是打開的,還是有一定道理的。在Visual C++ 2005中,默認情況下將會使用/GS選項
原帖:http://caiwei8888.blog.163.com/blog/static/30174241200811612656310/
VS2003=>VS2005在VC上的一些變化
1. 變量作用域
在vc7.1中, 如果一個變量定義在for語句的條件從句中,那麼這個變量可以在for之後使用。但Vc8禁止這樣,會報告一個C2065錯誤.
for (int i = 0; i < 10; ++i)
{
//codes here
}
if (i < 10).. //error in Vc8
for (i = 0; i < 5; ++i) //error in Vc8
解決方法:
在for語句之前聲明變量(可保證代碼在vc7.1和vc8下同時編譯通過)
int i =0;
for (i = 0; i < 10; ++i)
for (i = 0; i < 5; ++i)
2. 指針和引用的聲明
在Vc7.1中, 下面的代碼可以編譯, 但是vc8會報C4430 錯誤。(很難想象有些美國程序員竟然這樣聲明)
const & int a; //error in VC8
const * int b; //error in VC8
int myfun (const & B); //error in VC8
解決方法:
把* 或&放到類型的後面.
const int& a;
const int* b;
int myfun (const B&);
3. 默認int類型
在vc7.1中,如果定義一個變量但不聲明類型,那麼默認爲int。VC8不支持。
static i = 0; // C4430 error in Vc8
const i = 0; //C4430 error
解決方法:
加上int.
static int i = 0;
const int i = 0;
4. 函數的默認返回值類型
同上,VC8不支持把 int 作爲默認返回值類
Func()
{return 0;}; //error in VC8
解決方法:
明確聲明函數返回值類型爲 int.
int Func()
{return 0;};
5. 函數地址
Vc7中函數名就是地址。在vc8中,必須要使用&操作符同時寫出這個方法的全名(fully qualified name).
class A
{
public:
int Test(void);
};
void fun(int (A::*test) (void));
int main()
{
fun(A::Test);//C3867 error in VC
return 0;
}
解決方法:
加上 &.
fun(&A::Test);
6. 隱式類型轉換
VC8不允許B* 到const B*&的隱式轉換.
class B{};
void fun ( const B* & );//if possible use const B* instead
int main()
{
B *test = new B();
fun (test); //error in VC8
return 0;
}
解決方法:
強制轉換或函數參數變成const B*。
void fun ( const B* );
7. 友元方法(Friend function)
VC8不允許聲明一個private或protected函數爲友元.
class A
{
private:
void c();
};
class B
{
friend void A::c(); //C2248 error, c() is invisible to class B.
};
解決方法 1:
聲明友元類.
class A
{
private:
void c();
};
class B
{
friend class A;
};
解決方法 2:
把函數聲明爲public
class A
{
public:
void c();
};
class B
{
friend void A::c();
};
8. STL的stdext 命名空間
在vc8中,hash_map 和hash_set 被移進了stdext命名空間中.
#include <hash_map>
std::hash_map //error in VC8
解決方法:
使用stdext 命名空間.
#include <hash_map>
stdext::hash_map
9. 頭文件
許多頭文件如fstream.h 和iostream.h在VC8中已經不存在了.
#include <fstream.h> //error in VC8
解決方法:
使用STL.
#include <fstream>
10. Iterator
一些 STL 類, iterators 不再用指針實現
std::vector<DMDetailRow> m_data;
std::vector<DMDetailRow>::iterator iter = &m_data[rowNum];
解決方法:
std::vector<DMDetailRow>::iterator Iter = m_data.begin() + rowNum;
11. Enum
使用一個Enum的成員時,不要使用enum的名字
enum E
{
a,b,c
};
E e1 = E::a; //warning in VC8
解決方法:
去掉Enum 的名字.
E e1 = a; 此外, 還發現了不少函數聲明方面的變化:①ON_WM_NCHITTEST()出現下列錯誤:
錯誤 33 error C2440: “static_cast”: 無法從“UINT (__thiscall CGuiControlBar::* )(CPoint)”轉換爲“LRESULT (__thiscall CWnd::* )(CPoint)” ../guilib1.5/guilib/guicontrolbar.cpp 101
*需要使用LRESULT纔行!
②錯誤 22 error C3861: “tstrlen”: 找不到標識符 ../guilib1.5/guilib/guitabwnd.cpp 458
*在新的MSDN查不到strlen,使用 _tcslen
③錯誤 31 error C2664: “strcpy”: 不能將參數 1 從“WCHAR [32]”轉換爲“char *” ../guilib1.5/guilib/guidocktoolbarex.h 26 改爲_tcscpy,*看來在VS2005中處理字符串時不能再像以前那樣直接用C風格的了,還是用T形式的吧,既然strcpy要用_tcscpy,其它的字符串函數估計也只好用_tcsxxx了。
轉載:http://blog.csdn.net/sc_valentine21/article/details/6043574