我的代码:
m_ListCtrlCandidates.InsertItem(i, _itoa_s(candidate[i].ID, (char*)(LPCTSTR)str, 10));
m_ListCtrlCandidates.SetItemText(i, 1, _itoa(candidate[i].FingerNumber, (char*)(LPCTSTR)str, 10));
m_ListCtrlCandidates.SetItemText(i, 2, _itoa(candidate[i].SampleNumber, (char*)(LPCTSTR)str, 10));
m_ListCtrlCandidates.SetItemText(i, 3, _itoa(candidate[i].ConfidenceLevel, (char*)(LPCTSTR)str, 10));
错误:
Error 2 error C4996: '_itoa': This function or variable may be unsafe. Consider using _itoa_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. d:\documents\visual studio 2013\projects\gatekeeper\gatekeeper\gatekeeperdlg.cpp 416 1 Gatekeeper
我使用的SDK样本中包含以下代码。它将可能的匹配添加到对话框中的列表中。最初我将我的项目设置为unicode并更新代码以使其工作。这给了我麻烦,所以我查看了示例代码,它的字符集是空白的。所以我换了我的,现在我得到了这个错误。
如果我将其切换到_itoa_s,我会收到该函数没有3个参数的错误。所以我想我错过了尺寸参数,但我不确定它的尺寸是多少。此外,当它保留为_itoa时,它在示例代码中编译得很好。
我真的想把它保存在Unicode中。在其他地方使用_wtoi代替atoi有帮助。这种情况有类似的东西吗?
答案 0 :(得分:1)
我正在使用其示例中包含以下代码的SDK。
那太不幸了!
_itoa(candidate [i] .FingerNumber,(char *)(LPCTSTR)str,10)
我猜你正在使用MFC,str
是CString
,而你正在调用CListCtrl::SetItemText
。
(LPCTSTR)
上的CString
运算符获取指向保存字符串数据的基础缓冲区的指针。那是const TCHAR*
,所以如果你在ANSI模式下编译,这是一个指向字节的const char*
指针;在Unicode模式下,它是const wchar_t*
指向16位代码单元。
将其转换为非const char*
并要求_itoa
写入这是一个非常糟糕的主意。这会覆盖CString
中最初的内容,如果数字足够大,结果字符串比CString
中最初的字符串长,则可能会在数组的末尾写入,从而导致内存腐败严重。
在Unicode模式下将其转换为char*
甚至更奇怪,因为您使用wchar_t
数组作为char*
字节的存储空间。而Unicode模式中的SetItemText()
肯定会得到wchar_t
个字符吗?
在其他地方使用_wtoi代替atoi。是否有类似的东西
_itow
作为wchar_t
的{{1}}类似物存在。 (至少在VS中。这两种函数都不是标准的C [++]。)
您可以启用_itoa
并致电#ifdef _UNICODE
或_itoa
以匹配_itow
类型。但是,除非你真的需要支持一个古老的ANSI专用版本,因为有些遗留原因,这些天没有太多理由打扰TCHAR
切换。您通常可以坚持使用Unicode模式,并使用基于TCHAR
的字符串作为文本。
错误C4996:'_ ita':此函数或变量可能不安全。
Microsoft弃用了许多C函数,这些函数将可变数量的内容写入预先分配的缓冲区,因为缓冲区很容易太短,导致上述内存损坏恐怖。这是过去应用程序中无数安全问题的原因,因此最好避免使用。
不幸的是,警告4996实际上已经弃用了一些非常危险的标准函数,这非常令人厌烦,特别是因为其他编译器通常不支持wchar_t
版本作为替换。
在这种情况下虽然MS是正确的,_s
并不是真的安全。要安全地使用它,你必须为你传递的类型的最长整数分配一个足够大的缓冲区,而且很容易出错。
如果我将它切换到_itoa_s,我会得到错误,该函数不带3个参数。所以我想我错过了尺寸参数,但我不确定它的尺寸是什么
然而,在要写入的指针末尾有许多元素可用。所以目前这取决于你偷了缓冲区的_itoa
的长度。但这样做并不是一个好主意。您可以分配自己的缓冲区:
CString
这是安全的,虽然它仍然失败(使用errno wchar_t str[8];
_itow_s(candidate[i].FingerNumber, str, 8, 10);
)如果FingerNumber的数字超过7位,因为没有空间可以存储它们(包括EINVAL
终结符)。
像\0
那样将变量内容写入缓冲区的函数通常非常难看。如果您可以将现代C ++与STL一起使用,则可以使用更简单,更安全的字符串处理方法,例如:
itoa
(虽然这与老派MFC和CString的混合程度是另一个问题。)