我应该在MSVC - C上使用安全版本的POSIX函数吗?

时间:2010-07-08 11:46:59

标签: c cross-platform visual-c++ compiler-warnings deprecated

我正在编写一些预期在多个编译器上编译的C代码(至少在MSVCGCC上)。由于我是C语言的初学者,因此我打开了所有警告并将警告视为错误(GCC中的-Werror和MSVC中的/WX),以防止我犯下愚蠢的错误。

当我编译一些在MSVC上使用strcpy的代码时,我收到警告,如

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.

我有点困惑。许多常用功能在MSVC上已弃用。我应该在Windows上使用此安全版本吗?如果是,我应该将strcpy包裹起来,

my_strcpy()
{
#ifdef WIN32
 // use strcpy_s
#ELSE
 // use strcpy    
}

有什么想法吗?

3 个答案:

答案 0 :(得分:4)

关于此主题,有很多很多关于SO的讨论。我敢肯定,像strncpy,strlcpy等常见的嫌疑人会再次出现在这里。只需在搜索框中输入“strcpy”,然后阅读一些较长的线程即可获得概述。

我的建议是:无论您的最终选择是什么,最好遵循DRY原则并继续按照my_strcpy()的示例进行操作。不要在您的代码中抛出原始调用,使用包装器并将它们集中在您自己的字符串处理库中。如果您稍后改变主意,这将减少整体代码(样板文件),并且您有一个中心位置可以进行修改。

当然这会打开一些其他的蠕虫病毒,特别是初学者:内存处理责任和界面设计。这个主题本身和5个人都会给你10个如何做的建议。中央库通常具有很好的效果,它会强制执行一个决策,您将在整个代码库中执行该决策,而不是使用模块A中的方法a和模块B中的方法b,当您尝试将A与B连接时会导致麻烦。 ..

答案 1 :(得分:4)

每当你在非恒定大小的缓冲区之间移动数据时,你必须(喘气!omg!)实际思考它是否适合。使用声称“安全”的函数(如MS特定的strcpy_s或BSD strlcpy)将保护您免受某些明显的缓冲区溢出条件的影响,但不会保护您免受字符串截断导致的错误。在计算必要的缓冲区大小时,它也不会保护您免受整数溢出的影响。

除非你是处理C字符串的专家,否则我建议忘记特殊功能并评论代码的每个行,这些代码将执行可变长度/位置写入,并证明你是如何理由的知道,在程序的这一点上,你将要使用的长度/偏移量在缓冲区大小的范围内。对你对大小/偏移量进行算术运算的行也这样做 - 记录你如何知道算术不会溢出,如果你发现你不知道就加上溢出测试。

另一种方法是将所有字符串处理完全包装在一个字符串对象中,该字符串对象存储缓冲区的长度以及字符串,并在需要放大字符串时自动重新分配,然后仅使用const char *进行读取 - 当您需要将字符串传递给系统函数或其他库时,只能访问字符串。这将牺牲你期望从C中获得的一些性能,但它将帮助你确保你不犯错误。只是不要把它带到极端。您无需在字符串包装器中复制strchrstrstr等内容。只需提供复制字符串对象,连接它们并截断它们的方法,然后使用在const char *上运行的现有库函数,您可以执行任何您想要的操作。

答案 2 :(得分:1)

我倾向于使用更安全的函数snprintf†,它可以在两个平台上使用,而不是根据平台具有不同的路径。您需要使用define来阻止MSVC上的警告。

†​​虽然可能稍微不那么安全 - 它会返回一个字符串,该字符串在出错时不会以nul结尾,因此您必须检查返回,但不会导致缓冲区溢出。