问题
Recently I tried to use /Wall Visual C++ option to enable all warnings and found that the following code:
typedef BOOL ( WINAPI * TIsWow64ProcessFunction )( HANDLE, BOOL* );
TIsWow64ProcessFunction isWow64ProcessFunction = reinterpret_cast<TIsWow64ProcessFunction> (
::GetProcAddress( kernel32DllHandle, "IsWow64Process" ) );
spawned C4191:
warning C4191: 'reinterpret_cast' : unsafe conversion from 'FARPROC' to 'TIsWow64ProcessFunction'
Calling this function through the result pointer may cause your program to fail
If I use a C-style cast the same warning appears but now it mentions "type cast" instead of "reinterpret_cast".
The same warning is repeated for just any case I call GetProcAddress()
and convert its return value to some usable function pointer.
How do I address these warnings? Do I need to make alterations to my code?
回答1:
You are casting a FARPROC (function pointer with no args) to a function pointer with args. Normally this is a hugely dumb thing to do that will probably result in stack corruption.
Now it turns out that GetProcAddress() doesn't really return a FARPROC and you do actually know what you're doing -- but the compiler doesn't know that and it feels obliged to warn you.
The only way you can silence it is using a #pragma or a compiler switch to turn off the warning. It is ugly and messy, but that is Windows programming for you. :-)
回答2:
As other answers have already mentioned, this is a useful warning. Normally, this type of coercion would be a serious bug hiding in your application.
Therefore, you probably don't want to disable it globally with a compiler switch. Yet you still need to call GetProcAddress
, and you like your builds to compile cleanly without warnings.
You have two good options:
Suppress each individual warning using an MSVC-specific pragma. In a new line just above the maligned cast, add the following code:
#pragma warning(suppress: 4191)
This suppresses the warning for the very next line of code only, ensuring that it is not globally suppressed and you'll still get a warning if you try to do something stupid elsewhere in the code base. Of course, you'll need to add this each time you use
GetProcAddress
, which is kind of a pain. Worse yet, it's a non-portable, MSVC-specific extension that uglifies your code.So, alternatively…
You can silence the warning by explicitly casting the result of
GetProcAddress
(aFARPROC
) tovoid*
, and then casting thatvoid*
to the specific function-pointer type. For example:typedef BOOL ( __stdcall *TIsWow64ProcessFunction )( HANDLE, BOOL* ); TIsWow64ProcessFunction isWow64ProcessFunction = reinterpret_cast<TIsWow64ProcessFunction>( reinterpret_cast<void*>( ::GetProcAddress(hInstance, "IsWow64Process")));
This approach will work with other compilers, is slightly less ugly, and is arguably more semantically meaningful.
回答3:
Basically the compiler cannot guarantee that the function is of the appropriate type, so it's unsafe for you to call the resulting pointer. However, in a VS program you don't have to link or load against the Windows .dlls explicitly, they will be loaded for you and any function in the Windows header is always available to use.
来源:https://stackoverflow.com/questions/4192058/how-to-address-c4191-warning-around-calls-to-getprocaddress-with-farproc