我知道有一个类似的标题问题,但我想知道我对这个具体案例的选择。
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.
这是我的代码:
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_);
}
注意font_
是一个实例变量。 LOGFONT
是一种窗口结构,lfFaceName
定义为TCHAR lfFaceName[LF_FACESIZE]
。
我想知道的是,我可以做以下事情(如果不是,为什么不这样做):
void MyControl::SetFontFace(const std::string& faceName)
...
lf.lfFaceName = faceName.c_str();
...
或者如果完全有不同的选择,请告诉我。
答案 0 :(得分:8)
您收到安全警告的原因是,您的faceName
参数可能指向更长的字符串,而不是LF_FACESIZE
个字符,然后{{1}会盲目地覆盖strcpy
结构中lfFaceName
之后的任何内容。你确实有一个错误。
您应不通过将LOGFONT
更改为strcpy
来盲目修复错误,因为:
strcpy_s
函数是不可移植的Microsoft发明几乎所有这些函数都复制了 可移植的其他C库函数的功能。永远不要使用它们,即使是在不打算携带的程序中(如图所示)。*_s
(strcpy
,strncpy
,strlcpy
)的“安全”变体只会截断字符串,如果它太长,在这种情况下会让你尝试加载错误的字体。更糟糕的是,strcpy_s
在执行此操作时省略了NUL终止符,因此如果您使用该崩溃,则可能只是在strncpy
内移动崩溃。 正确的修复是预先检查长度,如果时间过长则无法完成整个操作。此时CreateFontIndirect
变得安全(因为你知道它不会太长),虽然我更喜欢strcpy
,因为它让我对这段代码的未来读者显而易见。memcpy
和TCHAR
不是一回事;将C样式char
字符串或C ++ const char *
复制到std::string
数组中而没有正确的编码转换可能会产生完全无意义的错误。 (根据我的经验,使用TCHAR
总是一个错误,最大的问题是像这样的代码似乎在ASCII构建中正常工作,并且仍然会编译 UNICODE模式,但在运行时会发生灾难性故障。)您当然可以使用TCHAR
帮助解决此问题,但它不会让您无需检查长度并手动复制字符串。我可能会这样做。请注意,我使用std::string
和LOGFONTW
以及CreateFontIndirectW
中UTF-8的显式转换。另请注意,其中的大块是MSDN中的货物,并且没有一个已经过测试。遗憾。
std::string
答案 1 :(得分:3)
lf.lfFaceName = faceName.c_str();
不,你不应该这样做,因为你正在为std :: string中保存的数据制作poitner的本地副本。如果c ++字符串发生更改或被删除,则指针不再有效,如果lFaceName决定更改数据,这几乎肯定会破坏std :: string。
由于你需要复制一个c字符串,你需要一个'c'函数,然后strcpy_s(或它的等价物)是安全的替代
答案 2 :(得分:0)
#include <cstdio>
#include <string>
using namespace std;
struct LOGFONT {
char lfFaceName[3];
};
int main() {
struct LOGFONT f;
string foo="bar";
f.lfFaceName = foo.c_str();
return 0;
}
导致
x.c:13: error: incompatible types in assignment of `const char*' to `char[3]'
我建议使用像警告所说的安全strcpy替代方案,因为无论如何你都知道目标空间的大小。
答案 3 :(得分:0)
lf.lfFaceName = faceName.c_str();
因两个原因无效(假设您将faceName更改为std:string)
在这里没有任何C ++可以提供帮助,因为lfFaceName是一个C“字符串”。您需要使用C字符串函数,如strcpy或strcpy_s。您可以将代码更改为:
strcpy_s(lf.lfFaceName, LF_FACESIZE, faceName);
答案 4 :(得分:0)
#include <algorithm>
#include <iostream>
#include <string>
enum { LF_FACESIZE = 256 }; // = 3 // test too-long input
struct LOGFONT
{
char lfFaceName[LF_FACESIZE];
};
int main()
{
LOGFONT f;
std::string foo("Sans-Serif");
std::copy_n(foo.c_str(), foo.size()+1 > LF_FACESIZE ? LF_FACESIZE : foo.size()+1,
f.lfFaceName);
std::cout << f.lfFaceName << std::endl;
return 0;
}