我正在将代码从 32 位 vs2012 迁移到 64 位 vs2015。
我在程序中遇到了以下函数调用:
CryptHashData(hHash,
(BYTE*)AUTH_ENCRYPTION_KEY,
wcslen(AUTH_ENCRYPTION_KEY) * sizeof(wchar_t),
0u))
其声明位于c:Program Files (x86)Windows Kits8.0Includeumwincrypt.h
wincrypt.h
(看起来不会被编辑(。
声明是:
WINADVAPI
BOOL
WINAPI
CryptHashData(
_In_ HCRYPTHASH hHash,
_In_reads_bytes_(dwDataLen) CONST BYTE *pbData,
_In_ DWORD dwDataLen,
_In_ DWORD dwFlags
);
DWORD dwFlags:这里的问题是
0u
是无符号的int,函数需要DWORD
。
为了解决此错误,我做了:
c-style
在功能call(tried size_t, unsigned int)
中(DWORD)(0U)
铸造static_cast
- 尝试创建一个新变量并将其强制转换
但警告仍然存在
看起来我必须在函数调用中进行更改
有人可以建议我如何解决这个问题。
请询问是否需要更多详细信息。
稍后的警告图像详细信息 警告图像详细信息
您认为 0u 是问题所在。
对我来说,看起来问题应该出在第三个参数上,其中size_t值用于馈送 dword 参数。
正如SomeProgrammerDude所解释的那样,在新环境中,size_t可能是64位,而DWORD是32位。这解释了新平台上的不匹配。
在 32 位平台上,您没有收到警告(我假设(,可能是因为那里size_t 32 位,没有丢失信息的风险。
您报告了强制转换会避免警告,这表明0u
不是问题所在。
警告似乎与0u
在线的事实可能是由于编译器抱怨整个函数调用并引脚指向它的末尾,即结束)
,恰好与0u
在同一行。
将所有)
移动到单独的行的实验(结果可见为两个屏幕截图的差异(已经证实了这一点。
请注意,强制转换仅避免了警告,这与解决问题不同。
(您明智地询问了铸造的安全性,我建议在单独的问题中这样做。
这个问题已经回答了。但是,我想就如何减少查看和分析此类警告所需的工作量提供额外的建议。我建议使用 PVS-Studio 静态代码分析器而不是编译器警告。它包含一组用于查找 64 位错误的专用诊断。首先,这组允许检测比任何编译器都能检测到的更多的错误,其次,分析器更智能。让我们回顾一个例子:
如果分析器不知道缓冲区的任何信息(理论上,字符串可能很大(,则分析器将生成警告。举个例子:
void F(DWORD);
void A(const wchar_t *AUTH_ENCRYPTION_KEY)
{
size_t s = wcslen(AUTH_ENCRYPTION_KEY) * sizeof(wchar_t);
F(s);
}
V107 隐式类型将函数"F"的第一个参数"s"转换为 32 位类型。 控制台应用程序1.cpp 15
但是,当分析器确定字符串较小且整数变量存储较小的值时,分析器将保持静默,并且不会生成不必要的警告。举个例子:
void F(DWORD);
void B(const wchar_t *src)
{
wchar_t AUTH_ENCRYPTION_KEY[100];
wcscpy_s(AUTH_ENCRYPTION_KEY, src);
size_t s = wcslen(AUTH_ENCRYPTION_KEY) * sizeof(wchar_t);
F(s);
}
分析器知道AUTH_ENCRYPTION_KEY缓冲区无法保存长度超过 99 个字符的字符串。因此,"s"变量将具有一个可以保证适合 DWORD 类型变量的值。PVS-Studio 分析器不会生成警告,这反过来又节省了开发人员将源代码移植到 64 位平台的时间。
附言我向所有从事 64 位应用程序开发的人推荐以下材料:64 位 C/C++ 应用程序的开发、真实程序中 64 位错误示例的集合、未定义的行为比您想象的更接近。