最近我尝试使用/Wall Visual C++ option启用所有警告,并发现以下代码:
typedef BOOL ( WINAPI * TIsWow64ProcessFunction )( HANDLE, BOOL* );
TIsWow64ProcessFunction isWow64ProcessFunction = reinterpret_cast<TIsWow64ProcessFunction> (
::GetProcAddress( kernel32DllHandle, "IsWow64Process" ) );
产生了C4191:
warning C4191: 'reinterpret_cast' : unsafe conversion from 'FARPROC' to 'TIsWow64ProcessFunction'
Calling this function through the result pointer may cause your program to fail
如果我使用C风格的强制转换,则会出现相同的警告,但现在它会提到“type cast”而不是“reinterpret_cast”。
对于我调用GetProcAddress()
并将其返回值转换为某个可用函数指针的任何情况,都会重复相同的警告。
如何解决这些警告?我是否需要对代码进行更改?
答案 0 :(得分:7)
您正在使用args将FARPROC(没有args的函数指针)转换为函数指针。通常,这是一个非常愚蠢的事情,可能会导致堆栈损坏。
现在事实证明GetProcAddress()并没有真正返回FARPROC并且你确实知道你正在做什么 - 但编译器并不知道这一点,并且它感到有必要警告你。
您可以使其静音的唯一方法是使用#pragma或编译器开关来关闭警告。这是丑陋和混乱,但这是Windows编程为您服务。 : - )
答案 1 :(得分:6)
正如其他答案已经提到的那样,这是一个有用的警告。 Normally, this type of coercion would be a serious bug hiding in your application
因此,您可能不希望使用编译器开关全局禁用它。然而,您仍然需要调用GetProcAddress
,并且您希望您的构建能够在没有警告的情况下进行干净的编译。
您有两个不错的选择:
使用特定于MSVC的编译指示抑制每个警告。在恶意演员阵容正上方的新行中添加以下代码:
#pragma warning(suppress: 4191)
这会抑制下一行代码 的警告,确保它不会被全局抑制,如果你试图在代码库中的其他地方做一些愚蠢的事情,你仍然会收到警告。当然,每次使用GetProcAddress
时都需要添加它,这是一种痛苦。更糟糕的是,它是一个不可移植的,特定于MSVC的扩展,可以使您的代码更加清晰。
所以,或者......
您可以通过明确地将GetProcAddress
(FARPROC
)的结果投射到void*
来消除警告,然后将void*
转换为特定的函数指针类型。例如:
typedef BOOL ( __stdcall *TIsWow64ProcessFunction )( HANDLE, BOOL* );
TIsWow64ProcessFunction isWow64ProcessFunction =
reinterpret_cast<TIsWow64ProcessFunction>(
reinterpret_cast<void*>(
::GetProcAddress(hInstance, "IsWow64Process")));
这种方法可以与其他编译器一起使用,稍微不那么难看,并且可以说在语义上更有意义。
答案 2 :(得分:2)
基本上编译器不能保证函数是合适的类型,因此调用结果指针是不安全的。但是,在VS程序中,您不必显式链接或加载Windows .dll,它们将为您加载,并且Windows标头中的任何函数始终可供使用。
答案 3 :(得分:1)
当我经常使用这种东西时,我也被这些警告所困扰。我喜欢@Cody Gray的答案,因为它仅在使用时抑制警告,但不会过滤掉其他可能有效的警告。
我做了一个简单的function_cast助手,使它更像c ++:
template<typename Result, typename Original>
Result function_cast(Original fptr)
{
return reinterpret_cast<Result>(reinterpret_cast<void *>(fptr));
}
OP的代码变为:
auto isWow64ProcessFunction = function_cast<TIsWow64ProcessFunction>(::GetProcAddress( kernel32DllHandle, "IsWow64Process" ) );