Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我应该在MSVC-C上使用POSIX函数的安全版本吗_C_Cross Platform_Visual C++_Compiler Warnings_Deprecated - Fatal编程技术网

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

我应该在MSVC-C上使用POSIX函数的安全版本吗,c,cross-platform,visual-c++,compiler-warnings,deprecated,C,Cross Platform,Visual C++,Compiler Warnings,Deprecated,我正在编写一些C代码,希望在多个编译器上编译(至少在MSVC和GCC上)。因为我是C语言的初学者,所以我打开了所有警告,并将警告视为错误(GCC中的-Werror,MSVC中的/WX),以防止我犯愚蠢的错误 当我在MSVC上编译了一些使用strcpy的代码时,我得到了如下警告: 警告C4996:“strcpy”:此函数或变量可能不安全。请考虑使用SrcPyPiS。要禁用弃用,请使用_CRT\u SECURE\u NO\u警告。有关详细信息,请参阅联机帮助。 我有点困惑。很多常用函数在MSVC上被

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

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

警告C4996:“strcpy”:此函数或变量可能不安全。请考虑使用SrcPyPiS。要禁用弃用,请使用_CRT\u SECURE\u NO\u警告。有关详细信息,请参阅联机帮助。

我有点困惑。很多常用函数在MSVC上被弃用。在Windows上是否应该使用此安全版本?如果是,我是否应该像

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

有什么想法吗?

我倾向于使用更安全的功能
snprintf
†,这在两种平台上都可用,而不是根据平台使用不同的路径。您需要使用define来防止MSVC上出现警告


†虽然安全性可能稍差-它将返回一个错误时未以nul结尾的字符串,因此您必须检查返回,但不会导致缓冲区溢出。

关于此主题,这里有很多讨论。我敢肯定,像strncpy、strlcpy之类的普通嫌疑犯会再次出现在这里。只需在搜索框中键入“strcpy”,并阅读一些较长的线程即可获得概述

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


当然,这也带来了其他一些麻烦,特别是对于初学者:内存处理责任和接口设计。这两个主题都是独立的,5个人会给你10条建议。中央库通常具有很好的效果,它强制执行一个决策,您将在整个代码库中遵循该决策,而不是使用模块A中的方法A和模块b中的方法b,这会在您尝试连接A和b时给您带来麻烦。

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

除非您是处理C字符串的专家,否则我建议您忘记特殊函数,并注释将执行可变长度/位置写入的代码的每一行,并在程序的这一点上说明您是如何知道的,要使用的长度/偏移量在缓冲区大小的范围内。在对大小/偏移量也执行算术的行中执行此操作-记录您如何知道算术不会溢出,如果您发现不知道,则添加溢出测试


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

谢谢。你是说我应该通过定义MSVC文档中所说的宏来抑制警告吗?@Appu无论如何,你应该使用“n”版本,这比非“n”版本更安全。如果您使用的是安全版本,那么警告会告诉您一些您已经缓解的问题,因此可以禁用它。我理解n版本给我们带来的好处。但这不是一种开销吗?考虑我需要复制一个长度未知的字符串。因此,我必须首先使用
strlen
计算长度,然后使用
strncpy
进行复制。本质上,字符串将迭代两次,
strcpy
只迭代一次。还是我遗漏了什么?strncpy不是“strcpy的安全版本”。它具有非常奇怪的行为,用于将数据存储在可能不以null结尾的固定宽度字段中。它还浪费了大量的时间零填充字符串末尾以外的区域。使用一个函数做不必要的工作并在调用后留下一团混乱,你必须检查和清理它,这是没有意义的。您可以同样轻松地使用
snprintf(dest,len,“%s”,src)
始终提供正确的行为(只要
len
适合
int
),谢谢。这是否意味着无论我做了什么,都将是我前进的方向,而不是压制警告信息?危险的问题。;)有些编译器有警告,我会考虑“过度偏执”。OTOH,甚至这些都是一个很好的提示,提示您应该更仔细地检查一些构造。该标准允许这些警告,甚至是一个“警告:您正试图编译为