經常寫VC工程的人都會遇到升級到VS2005時出現的各種各樣的問題,下面寫一些自己遇到的問題,還有什麼不全的請大家補充。希望能給朋友們一些幫助。

今天在將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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章