分类于 代码人生 | 120 次点击 | 评论(1) »
由 Apex 发表于

使用Visual Studio 2008写代码时,编译时遇到警告:

  1. 1>d:\program\msvs2008\vc\include\cstdio(49) : warning C4995: 'gets': name was marked as #pragma deprecated
  2. 1>d:\program\msvs2008\vc\include\cstdio(53) : warning C4995: 'sprintf': name was marked as #pragma deprecated
  3. 1>d:\program\msvs2008\vc\include\cstdio(56) : warning C4995: 'vsprintf': name was marked as #pragma deprecated
  4. 1>d:\program\msvs2008\vc\include\cstring(22) : warning C4995: 'strcat': name was marked as #pragma deprecated
  5. 1>d:\program\msvs2008\vc\include\cstring(23) : warning C4995: 'strcpy': name was marked as #pragma deprecated
  6. 1>d:\program\msvs2008\vc\include\cwchar(36) : warning C4995: 'swprintf': name was marked as #pragma deprecated
  7. 1>d:\program\msvs2008\vc\include\cwchar(37) : warning C4995: 'vswprintf': name was marked as #pragma deprecated
  8. 1>d:\program\msvs2008\vc\include\cwchar(39) : warning C4995: 'wcscat': name was marked as #pragma deprecated
  9. 1>d:\program\msvs2008\vc\include\cwchar(41) : warning C4995: 'wcscpy': name was marked as #pragma deprecated

意思是说,某个函数已经被标记为过时了,最好不要用,在将来的版本中,该函数可能就没有了,不存在了。

奇怪的是,代码里面并没有使用这些函数啊。但是先不考虑这个了,还是看看如何解决吧。对于编译器警告,当然可以用 #pragma warning(disable: xxxx ) 的语法将其禁止掉,这样编译时编译器就不会在那里唧唧歪歪了。在网上查找此类问题,基本上都是这样说的。

然后仔细想想,关闭这个警告并不正常,因为这样一来,所有过时的函数都不会再警告了,而我们可能是需要这个警告的,像是对于strcpy这种超常用的函数,考虑到安全性(应对缓冲区溢出攻击),我们的确应该使用其安全版本,例如strcpy就有对应的StringCchCopy/StringCbCopy这样的函数,如果关闭了此警告,我们就可能在代码中不小心写下strcpy,而不是其对应的安全版本(当然,strcpy等函数是特例,关闭C4995警告后,仍然会有其他警告,下面有说明)。

所以,考察上述几个函数,我们知道其函数声明所在的头文件,这些头文件中的函数应该都不会用到,所以可以用另一种方式来避免引入这些头文件:

在你的工程的预编译头文件(一般来说,就是stdafx.h)中,在 #pragma once 一行后面加上下列三行:

  1. #define _CSTDIO_
  2. #define _CSTRING_
  3. #define _CWCHAR_

这样,编译器就不会再加载 cstdio / cstring / cwchar 这几个头文件了。

P.S.
使用 #pragma warning(disable: xxxx) 这种方式关闭警告后,如果代码里面用到了 strcpy 这样的函数,编译器会报另一个警告:

  1. 1>e:\work\ncksoft\test\main.cpp(126) : warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
  2. 1>        d:\program\msvs2008\vc\include\string.h(74) : see declaration of 'strcpy'

所以我们仍然可以得到想要的警告信息。

再 P.S.
如果在代码中使用 #pragma deprecated( name_of_deprecated ) ,就会在编译时报 C4995 警告,而使用下面的方法,则会报 C4996 警告:

  1. __declspec(deprecated) void foo(int) {
  2.    // ...
  3. }

再 再 P.S.
我很讨厌那些将警告信息视作无物的程序员,一点美感都没有!