经常写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

阅读更多
上一篇vc多线程程序移植到vs2005以上,所遇到到映射问题
下一篇vc socket在debug模式下可以正常通讯,在release模式下经常通讯失败
想对作者说点什么? 我来说一句

java web开发中常遇到问题

2012年12月10日 47KB 下载

java中常见大小问题的解决

2012年04月25日 4.95MB 下载

beescms总结

2012年02月29日 9KB 下载

DLL基础练习

2011年09月12日 18.85MB 下载

matlab命令大全

2011年05月29日 49KB 下载

matlab使用过程中的常见问题解答

2013年07月13日 191KB 下载

没有更多推荐了,返回首页

关闭
关闭