2017-05-20

SDL检查不报错事件调查报告

Visual Studio 2013 VC项目默认是启用SDL检查的。通常而言,这会使得一些“过期”函数在编译时被报告Error。比如strcpy和inet_addr之类都会遇到这个问题。

理论上讲,这些过期函数的确不安全,或者说容易被不安全地调用。微软也很“贴心”地在编译器的报错信息中给出了解决方案,比如用strcpy_s和InetPton来替换,都不用你去搜解决办法了。所以按照我的习惯,一般是就地解决掉这些问题再往下走。

不过呢,可能有的人性子比较急,也有的时候是从旧项目移植,想快点编译完先跑一下看看效果。改代码毕竟要时间,从strcpy改成strcpy_s可能还好,而从inet_addr改到InetPton就真的没有想象中那么轻松。所以编译器也给出了另一种建议,你可以设上几个Macro,SDL也是可以被忽略的。

到此为止都还比较和谐,大家都是有商有量地做事情。然而当我腾出时间准备把过期函数扫扫干净,把同事临时加的Macro去掉之后一编译,问题来了——SDL这次怎么不报错了?

再三确认过vcxproj中已经没有了相关的Macro,并且SDL的确是打开了。但这次编译就是不会报错,似乎对我面前的strcpy视而不见。为什么呢?

Google上搜了一大圈也没有方向。最后还是被我排除法硬试出来的——平台工具集如果选了v120_xp,那么SDL即使打开,有些过期函数也不会报错。是不是SDL就此失效,我不清楚,因为我没法去覆盖所有的过期函数。我估计,微软是这样想的:你既然打算让这个程序跑在过期的OS上,那函数过期不过期已经不重要了。

其实还有一个更重要的原因:strcpy_s还好,但要是把inet_addr真的换成了InetPton,你就会发现在WinXP下你的程序根本就跑不起来。实际上,WinXP就不支持InetPton。MSDN上的信息表明,最低也要Vista才可以。

我们的程序暂时还不能抛弃WinXP用户,但若要完全不知道用了哪些过期函数我又心有不甘,于是我打算做一个#if……#else……#endif来解决这个过期OS兼容的问题。搜了一下,正确的姿势应该是:
#if (_WIN32_WINNT >= 0x602)
#else
#endif
最后我是在Debug版本上用了平台工具集v120,在Release时还是用了v120_xp。过期函数只会局限在以上Macro范围内,有限度地使用。

另外,WinXP也不支持条件变量CONDITION_VARIABLE,所以这个服役期超长的操作系统是真的应该淘汰了。我不得不说一句:WannaCry,干得好!

没有评论:

发表评论