如何解决使用FARPROC调用GetProcAddress周围的C4191警告?

sha*_*oth 9 c++ winapi casting function-pointers compiler-warnings

最近我尝试使用/ Wall Visual C++选项启用所有警告,发现以下代码:

typedef BOOL ( WINAPI * TIsWow64ProcessFunction )( HANDLE, BOOL* );
TIsWow64ProcessFunction isWow64ProcessFunction = reinterpret_cast<TIsWow64ProcessFunction> (
    ::GetProcAddress( kernel32DllHandle, "IsWow64Process" ) );
Run Code Online (Sandbox Code Playgroud)

产生C4191:

warning C4191: 'reinterpret_cast' : unsafe conversion from 'FARPROC' to 'TIsWow64ProcessFunction'
Calling this function through the result pointer may cause your program to fail
Run Code Online (Sandbox Code Playgroud)

如果我使用C风格的强制转换,则出现相同的警告,但现在它提到"类型转换"而不是"reinterpret_cast".

对于我调用GetProcAddress()并将其返回值转换为某个可用函数指针的任何情况,都会重复相同的警告.

我该如何处理这些警告?我是否需要对代码进行更改?

Mic*_*l J 7

您正在使用args将FARPROC(没有args的函数指针)转换为函数指针.通常,这是一个非常愚蠢的事情,可能会导致堆栈损坏.

现在事实证明,GetProcAddress()并没有真正返回FARPROC并且你确实知道你正在做什么 - 但编译器不知道这一点,并且它感到有必要警告你.

您可以使其静音的唯一方法是使用#pragma或编译器开关来关闭警告.这是丑陋和混乱,但这是Windows编程为您服务.:-)


Cod*_*ray 6

正如其他答案已经提到的那样,这是一个有用的警告.通常情况下,这种类型的强制操作会隐藏在您的应用程序中.

因此,您可能不希望使用编译器开关全局禁用它.然而,你仍然需要调用GetProcAddress,并且你喜欢你的构建版本在没有警告的情况下干净地编译.

你有两个不错的选择:

  1. 使用特定于MSVC的编译指示抑制每个警告.在恶意演员阵容上方的新行中,添加以下代码:

    #pragma warning(suppress: 4191)
    
    Run Code Online (Sandbox Code Playgroud)

    这抑制了的代码非常下一行的警告,确保它没有被全局抑制,你还是会得到一个警告,如果你尝试做一些代码库愚蠢别处.当然,每次使用时都需要添加它GetProcAddress,这是一种痛苦.更糟糕的是,它是一个不可移植的,特定于MSVC的扩展,可以使您的代码更加清晰.

    所以,或者......

  2. 您可以通过显式地将GetProcAddress(a FARPROC)的结果转换void*,然后将其void*转换为特定的函数指针类型来使警告静音.例如:

    typedef BOOL ( __stdcall *TIsWow64ProcessFunction )( HANDLE, BOOL* );
    
    TIsWow64ProcessFunction isWow64ProcessFunction =
        reinterpret_cast<TIsWow64ProcessFunction>(
           reinterpret_cast<void*>(
           ::GetProcAddress(hInstance, "IsWow64Process")));
    
    Run Code Online (Sandbox Code Playgroud)

    这种方法可以与其他编译器一起使用,稍微不那么难看,并且可以说在语义上更有意义.