How to address C4191 warning around calls to GetProcAddress with FARPROC? - c++

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?

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. :-)

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 (a FARPROC) to void*, and then casting that void* 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.

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.

I was bothered also by these warnings as I use this sort of thing quite often. I liked #Cody Gray's answer as it suppresses the warning only at the point of use but doesn't filter out other possibly valid warnings.
I made a simple function_cast helper to make it a bit more c++ like:
template<typename Result, typename Original>
Result function_cast(Original fptr)
{
return reinterpret_cast<Result>(reinterpret_cast<void *>(fptr));
}
The OP's code becomes:
auto isWow64ProcessFunction = function_cast<TIsWow64ProcessFunction>(::GetProcAddress( kernel32DllHandle, "IsWow64Process" ) );

Related

Mark variable as not NULL after BOOST_REQUIRE in PVS-Studio

I'm using PVS-Studio to analyze my Testcode. There are often constructs of the form
const noAnimal* animal = dynamic_cast<noAnimal*>(...);
BOOST_REQUIRE(animal);
BOOST_REQUIRE_EQUAL(animal->GetSpecies(), ...);
However I still get a warning V522 There might be dereferencing of a potential null pointer 'animal' for the last line.
I know it is possible, to mark functions as "not returning NULL" but is it also possible to mark a function as a valid NULL check or make PVS-Studio somehow else aware that animal can't be NULL after BOOST_REQUIRE(animal);?
This also happens if the pointer is checked via any assert flavour first.
Thank you for the interesting example. We'll think, what we can do with the BOOST_REQUIRE macro.
At the moment, I can advise you the following solution:
Somewhere after
#include <boost/test/included/unit_test.hpp>
you can write:
#ifdef PVS_STUDIO
#undef BOOST_REQUIRE
#define BOOST_REQUIRE(expr) do { if (!(expr)) throw "PVS-Studio"; } while (0)
#endif
This way, you will give a hint to the analyzer, that the false condition causes the abort of the control flow.
It is not the most beautiful solution, but I think it was worth telling you about.
Responding to a comment with a large one is a bad idea, so here is my detailed response on the following subject:
Although this is possible it would be a pain to include that define in
all testcase files. Also this is not limited to BOOST_REQUIRE only but
also applies to assert, SDL_Assert or any other custom macro the user
might use.
One should understand that there are three types of test macros and each should be discussed separately.
Macros of the first type simply warn you that something went wrong in the Debug version. A typical example is assert macro. The following code will cause PVS-Studio analyzer to generate a warning:
T* p = dynamic_cast<T *>(x);
assert(p);
p->foo();
The analyzer will point out a possible null-pointer dereferencing here and will be right. A check that uses assert is not sufficient because it will be removed from the Release version. That is, it turns out there’s no check. A better way to implement it is to rewrite the code into something like this:
T* p = dynamic_cast<T *>(x);
if (p == nullptr)
{
assert(false);
throw Error;
}
p->foo();
This code won’t trigger the warning.
You may argue that you are 100% sure that dynamic_cast will never return nullptr. I don’t accept this argument. If you are totally sure that the cast is ALWAYS correct, you should use the faster static_cast. If you are not that sure, you must test the pointer before dereferencing it.
Well, OK, I see your point. You are sure that the code is alright, but you need to have that check with dynamic_cast just in case. OK, use the following code then:
assert(dynamic_cast<T *>(x) != nullptr);
T* p = static_cast<T *>(x);
p->foo();
I don’t like it, but at least it’s faster, since the slower dynamic_cast operator will be left out in the Release version, while the analyzer will keep silent.
Moving on to the next type of macros.
Macros of the second type simply warn you that something went wrong in the Debug version and are used in tests. What makes them different from the previous type is that they stop the algorithm under test if the condition is false and generate an error message.
The basic problem with these macros is that the functions are not marked as non-returning. Here’s an example.
Suppose we have a function that generates an error message by throwing an exception. This is what its declaration looks like:
void Error(const char *message);
And this is how the test macro is declared:
#define ENSURE(x) do { if (!x) Error("zzzz"); } while (0)
Using the pointer:
T* p = dynamic_cast<T *>(x);
ENSURE(p);
p->foo();
The analyzer will issue a warning about a possible null-pointer dereferencing, but the code is actually safe. If the pointer is null, the Error function will throw an exception and thus prevent the pointer dereferencing.
We simply need to tell the analyzer about that by using one of the function annotation means, for example:
[[noreturn]] void Error(const char *message);
or:
__declspec(noreturn) void Error(const char *message);
This will help eliminate the false warning. So, as you can see, it’s quite easy to fix things in most cases when using your own macros.
It might be trickier, however, if you deal with carelessly implemented macros from third-party libraries.
This leads us to the third type of macros. You can’t change them, and the analyzer can’t figure out how exactly they work. This is a common situation, as macros may be implemented in quite exotic ways.
There are three options left for you in this case:
suppress the warning using one of the false-positive suppression means described in the documentation;
use the technique I described in the previous answer;
email us.
We are gradually adding support for various tricky macros from popular libraries. In fact, the analyzer is already familiar with most of the specific macros you might encounter, but programmers’ imagination is inexhaustible and we just can’t foresee every possible implementation.

How to implement a runtime debug assertion without macros in C++ 11/14 with type safety?

An assertion to be used in a context like:
ASSERT(dynamic_cast<Derived*>(_ptr));
ptr = static_cast<Derived*>(ptr);
So during debugging the assertion will check the dynamic cast but will be removed for the release mode. (standard assertion behaviour)
How can I implement this using without macros. What I was thinking was:
void ASSERT(bool _arg)
{
if(!_arg)
//something
}
However, this doesn't ensure type safety. Additionally, I was thinking of having two implementations of this, one which is empty(for release, so the ASSERT function does nothing) and another with the code above for debug. This method would also rely on the compiler optimising out the empty function, something which is not always reliable.
Therefore, what would be the best way to go about it? Or are macros absolutely necessary...?
The benefit of using macros for this purpose over functions is as you said, there is a chance that the check won't be completely optimised out and you'll still pay for the dynamic_cast.
Your best option is to use assert(dynamic_cast<Derived*>(_ptr) != nullptr). Type safety doesn't buy you anything for assert-like behaviour.
If you must write your own function, you can conditionally call std::abort from the <cstdlib> header, but you'll have to add any diagnostic information yourself.

Disabling "cast from pointer to smaller type uint32_t" error in Clang

I'm working on a school project that involves porting a large piece of C++ code on an experimental piece of hardware. Unfortunately, that hardware is 64-bit and the code contains many instances of pointer arithmetic that expects pointers to be 32-bit, i.e. it often does reinterpret_cast<uint32_t>(ptr).
Going through them one by one would be very tedious and since this is an experimental project anyway, I'm happy to settle for a "hackish" workaround. So instead I modified the implementation of malloc to ensure it never allocates memory above the 4GB limit. Technically, these casts should therefore be valid.
Question is, how do I explain this to Clang? The error I'm getting is: error: cast from pointer to smaller type 'uint32_t' (aka 'unsigned int') loses information. Is there a way to disable it?
Thanks,
David
I was able to disable this with -fms-extensions after getting this from someone on the Cpplang Slack:
Looking at "DiagnosticSemaKinds.td" it shows up as err_bad_reinterpret_cast_small_int, https://github.com/llvm-mirror/clang/blob/release_50/include/clang/Basic/DiagnosticSemaKinds.td#L6193
There are two occurences in "SemaCast.cpp" -- one of which suggests it's sensitive to MS extensions, https://github.com/llvm-mirror/clang/blob/release_50/lib/Sema/SemaCast.cpp#L2112
One could try -fms-extensions (hopefully not -fms-compatibility), but that would bring all the shebang with it.
I agree that you should bite the bullet and fix the code to use the correct integer type. But to answer your question: No, you can't disable it, though you can work around it.
Many errors come from warnings. A good thing in general, but if you want to disable the warning, just do it. Since the culprit is probably something like -Wall which enables many warnings you should keep on, you should selectively disable this single warning. The error message mentions the diagnostic responsible for error message, e.g. ... [-Wextra-tokens] (if it doesn't, remove the -fno-diagnostics-show-option flag). You can then disable this diagnostic completely by adding -Wno-extra-tokens (again, the "extra tokens" warning is an example), or turn it into a non-fatal warning by means of -Wno-error=extra-tokens.
However, this specific error is not due to a warning and I can't find any option to disable errors (makes sense, since most errors are fatal).
But to just truncate the integer value and not having to fix all the wrong uses of uint32_t just yet, you could use static_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr)). Needless to say, this will still be wrong.
how about using uintptr_t, most of your pointer arithmetic may still works.
Save this piece of code as mycast.hpp and add -include mycast.hpp to your Makefile.
#include <cstdint>
template<typename U, typename T>
U Reinterpret_cast(T *x) {
return (U)(uintptr_t)x;
}
template<typename U, typename T>
U Reinterpret_cast(T &x) {
return *(U*)&x;
}
#define reinterpret_cast Reinterpret_cast
They should do their job unless your code is too tricky.
Your strategy will not work for stack-allocated objects, be careful!! You can insert some debugging/logging logic to Reinterpret_cast if necessary.
I hit this same problem in a project without C++11, and worked around it like this:
inline int PtrToInt(void* ptr)
{
void* clang[1];
clang[0] = ptr;
return *(int*)clang;
}

Unexpected compiler error (Superfluous Cast?)

I'm currently in the process of writing my own kernel bottom up, and I've come across this little issue in my linear memory manager, that I can't seem to understand.
I've got the following piece of code;
void* end_page_address = /*(void*)*/ 0x3FF000;
However, when the void pointer cast is disabled, I get the following error by g++;
src/paging/LinearMemoryManager.cpp: In constructor 'LinearMemoryManager::LinearMemoryManager(PhysicalMemoryManager*)':
src/paging/LinearMemoryManager.cpp:87:42: error: invalid conversion from 'int' to 'void*' [-fpermissive]
How come? - Because it's apparently not generally needed, as the line just above it compiles just fine without a cast:
void* start_page_address = 0x00000000;
I think that the NULL pointer, which has address 0, (even written as 0x00000 or similar), deserves a specific treatment in the C++ specification (and inside the GCC compiler). BTW, C++11 added nullptr and its type with good reasons.
But non-zero addresses like void* end_page_address = (void*) 0x3FF000; need an explicit cast.
I hope you are aware of C++ tricks (exceptions, constructors, RTTI, ...) when coding a kernel with it. You might need to understand exactly how your particular version of g++ handles them.
I also hope your kernel is free software (GPL-ed), and that you follow the "release early, release often" motto. I'll be curious to look inside its source code.

passing boost python enum as parameter

I defined
enum_<mytype>("mytype")
.value("one",1)
.value("two",2)
;
in my BOOST_PYTHON_MODULE.
when I expose a class with a function taking a parameter of type mytype (essentially, an int), like:
void myfunc(mytype m) {
...
}
I get the following compiler warning:
dereferencing pointer 'p.2311' (or whatever) does break strict-aliasing rules
now, it is just a warning, and the code works perfectly with optimization enabled..
may I safely ignore the warning? am I missing something?
Thank you
It's hard to say exactly without seeing the warning, but it's most likely caused by some macros from Python headers. To be safe, compile the code that uses Python (and Boost.Python) with -fno-strict-aliasing.