Macro redefinitions with header units - c++

I'm experimenting with header units. Currently, I'm testing in Visual Studio 2022(Version 17.2.3).
I'm currently importing multiple header units, for example
import <windows.h>;
import <thread>;
warning warning C4005: '__analysis_assume': macro redefinition 1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared\specstrings_strict.h(933): message : see previous definition of '__analysis_assume'
It kind of make senses because if <thread> and <windows.h> have any shared headers normally the inclusion guards or pragma once would prevent them from being included and being multiply defined.
I'm not really sure how header units can work if they shared header files with macros which a majority of header files of external libraries use.
I'm sure I can ignore the warning but I'm curious if anyone else has a better solution.

It seems this is a known issue with import causing multiple macro redefinitions when using windows.h.
https://developercommunity.visualstudio.com/t/warning-C4005:-Outptr:-macro-redefinit/1546919
We will have to wait for Microsoft to address this issue.

Related

When trying to compile a .dll, I'm getting an error with the interface keyword

I have set up a project in Visual Studio to create a .dll. I have included an external library in the project which uses the keyword "interface". This is giving me the following error:
error C2146: syntax error : missing ';' before identifier 'INuiAudioBeam'
These are the lines of code where the error occurs:
#ifndef __INuiAudioBeam_FWD_DEFINED__
#define __INuiAudioBeam_FWD_DEFINED__
typedef interface INuiAudioBeam INuiAudioBeam; //Error on this line
#endif
The above code is part of a header file in the external library I have included. The project builds successfully without any errors when compiling without including the headers for the library (Note: Linking the library does not cause any problems).
What is the solution to this? Is it because I have an external library I'm using to create my dll? Should I create a .lib instead of a dll?
If anyone else searches this, the problem is most likely
#define WIN32_LEAN_AND_MEAN
Before
#include <windows.h>
Remove the define, make sure your including windows.h, and that should define interface keyword for you
You can get C2146 with indictment of the interface keyword. It may be confusing as to how a keyword may be undefined, especially that in other compilation units or projects that use the same header file - the inclusion of which brought about the problem - all goes smooth. However, the apparent keyword "interface" is still a compiler #define directive. It just happens to be buried inside a header file that a few developers have reasons to inspect: the <objbase.h>. There it is defined in two steps:
#define __STRUCT__ struct
#define interface __STRUCT__
Since the <objbase.h> is included by multiple other header files - such as ole2.h, oleauto.h, and a slew of ATL headers - you may be surprised with this error when none of those headers were included in the current compilation unit.

How can I identify the header that generates a warning?

I'm sure that many of you are familiar with this set of warnings. These are most of the time generated by a include file. Solution is pragma push/disable/pop, but identifying the header is not a nice task.
Does anyone knows a way of identifying the header except trial-and-error ?
1>File1.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(49) : warning C4995: 'gets': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(53) : warning C4995: 'sprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstdio(56) : warning C4995: 'vsprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstring(22) : warning C4995: 'strcat': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cstring(23) : warning C4995: 'strcpy': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(36) : warning C4995: 'swprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(37) : warning C4995: 'vswprintf': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(39) : warning C4995: 'wcscat': name was marked as #pragma deprecated
1>C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\cwchar(41) : warning C4995: 'wcscpy': name was marked as #pragma deprecated
1>Linking...
In my case, moving #include <strsafe.h> to the bottom of the list got rid of the warning without using extra compiler directives.
A good way to find out where #pragma deprecated was being called was to go into the compiler settings under "Preprocessor" and to set Generate Preprocessed File to something like With Line Numbers (/P). Rebuild, then open up the *.i file and search for deprecated. Nearby will be the name of the offending include.
I'm using VS2003, so the dialogs may be slightly different for you.
The standard include files should have include guards. So you may be able to explicitly include those files at the top of your own file, with that warning disabled:
#pragma warning(push)
#pragma warning(disable: 4995)
#include <cstdio>
#include <cstring>
#include <cwchar>
#pragma warning(pop)
// rest of your #includes
That way the warnings will be disabled for the headers where you know there are problems. This needs to be at the top of your code so the headers are included for the first time inside the warning-disabled section.
I would like to second what #Celdecea said.
Clearly it would be nice if MS did what GCC does and specified the included path (stack?) for the file, which I presume is what you were looking for; unfortunately, I was unable to find a compiler directive to do that, so grepping through the .i file was a painful but effective replacement.
I too found that my problem stemmed from adding #includes after <strsafe.h>. Since my error list was (almost?) identical to yours I wouldn't be surprised if that also solves your problem.
If not, or if you wish to employ the pragma push/disable/pop style, then it seems that #Greg has the best solution in preemptively and explicitly defining those headers that are causing you pain.
The notes for #include strsafe.h include the line:
To use the Strsafe functions inline, include the header file as shown here, following the #include statements for all other header files.
In the MSDN offline help it says:
Important: The include line for strsafe.h should follow all other headers' include lines.
Make sure that you've only included in cpp files and after all other c++ library header files and the warnings goes away.
Kevin
To add to Greg Hewgill's post, I found the problem in set and I did not suspect this file.
#pragma warning(push)
#pragma warning(disable: 4995)
#include <set>
#pragma warning(pop)
Doing the above solved my problem.
In Visual Studio 2010 (and probably other versions too) set the C++/advanced 'show includes' option to Yes or add the /showIncludes command line option.
Then compile one file at a time and search the build output window for the warning number that you're looking for and it will show the tree of include files that is generating that warning.
This technique is useful for most build problems caused by include files.
EDIT: make sure you turn off /showIncludes when the problem is fixed as it can interfere with other compiler options (e.g. /MP (Build with Multiple Processes) is disabled).
To suppress the warning add the offending include files to a 4995 suppression block as suggested by Greg Hewgill above. This can either be at the top of the source file or in a precompiled header or in a 'forced' include file included across the project (C++/Advanced/Forced Include File).
The particular problem with 4995 CRT deprecation errors is that they seem to be generated every time code calls deprecated functions even if warning 4995 was suppressed when the deprecated functions were declared.
In my case for VS2008 these warnings were coming from #include <vector> (or some other std library.) It seems like Microsoft can't follow their own advice.
Doing the following fixed the issue:
#pragma warning(push)
#pragma warning(disable: 4995)
#include <vector>
#pragma warning(pop)
Just make sure that you do it as early as possible in your includes.

How to prevent macro redefinition

After working some time on my project, this warning begins to appear:
2>Game.cpp
2>c:\program files\microsoft sdks\windows\v6.0a\include\windef.h(126) : warning C4005: 'APIENTRY' : redefinición de macro
2> c:\users\ferran\directo\gameprojects\dev-libs\glfw\include\glfw.h(72) : vea la definición anterior de 'APIENTRY'
2>c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(23) : warning C4005: 'WINGDIAPI' : redefinición de macro
2> c:\users\ferran\directo\gameprojects\dev-libs\glfw\include\glfw.h(88) : vea la definición anterior de 'WINGDIAPI'
I'm sure that it's a matter of the order of the include files to solve, because none of these files are mine. My question is if there is a generic way to prevent this or to find which files must to be reordered to avoid this message.
The error message itself is telling you the incorrect order. It says that windef.h and wingdi.h are redefining symbols that were defined in glfw.h.
Put glfw.h after the Windows include files.
Microsoft doesn't generally design headers to be free-standing. Most of the Windows-oriented headers require that you have first included <windows.h>. Except for the dependency on that Mother Of All Headers, usually there are no specific header dependencies so by including <windows.h> first you shouldn't have any problem.
The problem is in the file Game.cpp. Try to include windows.h before glfw.h. There is a guard in glfw.h which will prevent that warning:
#ifndef APIENTRY
#ifdef _WIN32
#define APIENTRY __stdcall
#else
#define APIENTRY
#endif
#define GL_APIENTRY_DEFINED
#endif // APIENTRY
Unfortunately or fortunately, no. There is no such tool that automates it. You have to go read the code in those header files, figure out what is going on and take appropriate actions.
The most you can do is
Check if macro is defined using ifdef or if defined(...) or if !defined(...) preprocessor constructs.
Undefine macro using undef.
Only ANSI C considers macro redefinition an error.
This may be caused by Visual Studio pre-compiling headers for you. Be sure that all standard and microsoft headers are included before yours. Don't include microsoft headers in any of your .h files (it looks like you have windef.h and wingdi.h inlcuded in your glfw.h). Be sure that all your headers are side-effect free. The problem should then go away. Figuring out exactly what is causing it is generally very hard.

How to not #include <windows.h>

Using MSVC2008, 32bit on 64bit system.
I was once advised to never include windows.h as 'its a real monster and will slow down my compile times significantly'.
I tried leaving it out and obviously get compile errors. I included windef.h to define all the DWORDs etc, but I quickly come unstuck knowing what else to define to get the code to compile.
I now get:
2>c:\program files\microsoft sdks\windows\v7.0\include\winnt.h(6361) : error C2146: syntax error : missing ';' before identifier 'ContextRecord'
2>c:\program files\microsoft sdks\windows\v7.0\include\winnt.h(12983) : error C2065: 'PCONTEXT' : undeclared identifier
Can anyone suggest the right approach here?
Thanks
Simon
Use precompiled headers to improve compile times, and include windows.h.
Internally, windows.h respects many defines, like NOMINMAX or WIN32_LEAN_AND_MEAN.
It reduces the times significantly.
The correct answer would be "include it in the PCH". Pre-compiled headers reduce compilation time dramatically, and, contrary to popular belief, this is true also for Full Rebuilds.
If you have more than one CPP file in your project, the "Rebuild all" would build it once for the whole project, which merely ads a few seconds to compile time - to have windows.h included in all of them.
Research the APIs and make sure the headers are included in the correct order. It's not hard to not use Windows.h; but you'll learn about the MS headers in the process.
There are a few headers you have to be aware of:
WTypes.h
WinDef.h
WinBase.h
WinObject.h

Visual Studio 2008, error c2039: 'set_new_handler' : is not a member of 'std'

So the other day I went to compile a VC++ project I am working on and all of a sudden I get errors in almost all of my files saying:
new.h: error C2039: 'set_new_handler' : is not a member of 'std
new.h: error C2039: 'set_new_handelr' : symbol cannot be used in a using-declaration
"new.h" and 'set_new_handler' are not being used in any of my files, so I have no idea how or why these errors are suddenly appearing since they relate to a windows/VS library file.
Would anyone know what I can do to clear this error and compile my code again?
UPDATE After examining the files being included upon compilation, some files are including and some are . The problem is that is being included in afxwin.h and is being included in a third-party library. I honestly have no idea what to do with this problem...no other developers that have played with this code are running into this problem, may it be a settings problem? I am not using precompiled headers.
If I were to hazard a guess, I would say that <new.h> declares set_new_handler in the global namespace and <new> declares it within the std namespace. Some code is including <new.h> and expecting it to act as if it had included <new>. I would suspect either some 3rd party library/header or a precompiled header as suggested by Evan.
You can narrow down the culprit using either /showIncludes or pre-processing a source code file (using /E) and examining the output. I usually use the latter and look at the #line directives in the output file to figure out the include chain.
Good luck.