Use*_*ser 2 c++ stdstring strcpy
我知道有一个类似的标题问题,但我想知道我对这个具体案例的选择.
MSVC编译器发出有关strcpy的警告:
1>c:\something\mycontrol.cpp(65): 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.
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
void MyControl::SetFontFace(const char *faceName)
{
LOGFONT lf;
CFont *currentFont = GetFont();
currentFont->GetLogFont(&lf);
strcpy(lf.lfFaceName, faceName); <--- offending line
font_.DeleteObject();
// Create the font.
font_.CreateFontIndirect(&lf);
// Use the font to paint a control.
SetFont(&font_);
}
Run Code Online (Sandbox Code Playgroud)
注意font_是一个实例变量.LOGFONT是一个windows结构,lfFaceName定义为TCHAR lfFaceName[LF_FACESIZE].
我想知道的是我可以做以下事情(如果不是为什么不这样做):
void MyControl::SetFontFace(const std::string& faceName)
...
lf.lfFaceName = faceName.c_str();
...
Run Code Online (Sandbox Code Playgroud)
或者如果有完全不同的替代方案,请告诉我.
您获得安全警告的原因是,您的faceName参数可能指向一个比字符长的字符串,LF_FACESIZE然后strcpy会盲目地覆盖结构lfFaceName中的任何内容LOGFONT.你有一个错误.
你应该不会改变盲目修复bug strcpy来strcpy_s,这是因为:
*_s功能是不可移植微软的发明,几乎所有这些重复的其他C库函数的功能是便携.永远不要使用它们,即使是在一个不打算携带的程序中(如图所示).strcpy(strncpy,strlcpy,strcpy_s)只是截断字符串,如果它太长,在这种情况下,将让你尝试加载错误的字体.更糟糕的是,strncpy 当它这样做时,省略了NUL终结器,所以CreateFontIndirect如果使用那个,你可能只是将崩溃移到里面.在正确的解决方法是前面检查的长度,如果它是太长无法全部操作.在这一点上strcpy变得安全(因为你知道它不会太长),虽然我更喜欢,memcpy因为它让我想到的代码的未来读者显而易见.TCHAR并且char是不一样的东西; 将C风格的const char *字符串或C++ 复制std::string到TCHAR没有正确编码转换的数组中可能会产生完全无意义的错误.(根据TCHAR我的经验,使用is总是一个错误,最大的问题是像这样的代码似乎在ASCII构建中正常工作,并且仍然会在UNICODE模式下编译,但在运行时会发生灾难性的失败.)你当然可以std::string用来帮助解决这个问题,但它不会让你不需要检查长度并手动复制字符串.我可能会这样做.请注意,我正在使用LOGFONTW和CreateFontIndirectW来自UTF-8的显式转换std::string.另请注意,其中的大块是MSDN中的货物,并且没有一个已经过测试.抱歉.
void MyControl::SetFontFace(const std::string& faceName)
{
LOGFONTW lf;
this->font_.GetLogFontW(&lf);
int count = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
faceName.data(), faceName.length(),
lf.lfFaceName, LF_FACESIZE - 1)
if (count <= 0)
throw GetLastError(); // FIXME: use a real exception
lf.lfFaceName[count] = L'\0'; // MultiByteToWideChar does not NUL-terminate.
this->font_.DeleteObject();
if (!this->font_.CreateFontIndirectW(&lf))
throw GetLastError(); // FIXME: use a real exception
// ...
}
Run Code Online (Sandbox Code Playgroud)