VS2008 to VS 2010 migration - a breaking change? - c++

I encountered a problem when migrating our C++ code from VS2008 to VS2010. I can't find an explanation for the reason of it so far and will appreciate your help.
We have a custom memory allocator and it resides in a dll. In the rest of the code we use the preprocessor to redirect the allocations to our functions. Thie following simple code compiles correctly in VS2008, but does not in VS2010.
in stdafh.h:
#define free my_free
#include <string>
In VS2010 I get:
1>d:\program files\microsoft visual studio 10.0\vc\include\xdebug(62): error C3861: 'free': identifier not found
Coming from the line:
template<class _Ty>
void __CLRCALL_OR_CDECL _DebugHeapDelete(_Ty *_Ptr)
{ // delete from the debug CRT heap even if operator delete exists
if (_Ptr != 0)
{ // worth deleting
_Ptr->~_Ty();
// delete as _NORMAL_BLOCK, not _CRT_BLOCK, since we might have
// facets allocated by normal new.
free(_Ptr);
Any help or ideas will be highly appreciated!
Moshe

According to the C++ ISO standard, section 17.4.3.1.1.2:
A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.
This means that it's not legal to #define a library function name to mean something else. I guess this just happened to work in VS2008, but when migrating to VS2010 the compiler authors came up with an implementation in which this does not work properly.
If you want to redefine what free does, I suggest doing it through a more conventional channel by linking the code against your own implementation of the C library that changes the default behavior.

After some investigation using the /P option to create the preprocessor files and studying them I've found the root cause of the issue.
The xdebug header, which describes itself as "debug heap support header for Microsoft", contains the following lines:
#pragma push_macro("free")
#undef free
which obviously defeat our attempts to redefine it. So this is not something new to the compiler, just plain #undef that happens to occur with the functions we try to redefine

Related

Why do I get a linter error when I include std::vector? [duplicate]

This question already has answers here:
Visual Studio Code, #include <stdio.h> saying "Add include path to settings"
(14 answers)
Closed 1 year ago.
This is a problem that seem to occur from time to time for me. The linter says that "namespace std has no member 'vector'" although the program compiles and runs fine. The only problem besides the annoyance is that I cannot use the ctrl-click feature on the GameObject-class. The linter (intellisense) does not find it. I have tried to run a clean solution and recompile, as well as delete the temp-folder and the hidden .vs- file to no avail.
#include "GameObject.h"
#include "GraphManager.h"
#include <vector>
class GameObjectManager
{
static std::vector<GameObject> myGameObjects;
void CheckCollisions();
static int myIDCount;
public:
GameObjectManager() = default;
static void Init();
static GameObject& GetGameObject(const int index) { return myGameObjects.at(index); };
static void Update(const float aDeltaTime);
static void Render();
};
enter image description here
Which linter are you using?
Basically a linter tries to "compile" - meaning to look at - your source code pretty much the same way the compiler does. But for this to work, the C++ "environment" - meaning: the include paths, predefined macros and compiler options - must be (nearly) the same as the ones the compiler uses.
For example: If you compile your code in "release" configuration, several predefined and "by-convention" macros are set, such as NDEBUG, _WIN32 and others. Other macros such as _DEBUG are not set.
The microsoft std::vector implementation depends heavily on such macros. Depending on the macros it enables or disables features such as different levels of iterator validation in debug builds etc...
When you use a (non-microsoft) linter and run "lint.exe" (or whatever it is), you must make sure (define on the linter command line), that "lint.exe" is started with the same set of macros, include paths etc... as the compiler cl.exe.
If that is not the case, the missing macros may well cause the linter to miss the entire std::vector definition.
Or - alternatively - the linter is not good enough to untangle the internal web of macros. The namespace std { } statement for example might not be written verbatim in <vector>, but might require macro expansion and possibly a lot of it. If the linter has problems doing that, vector might be defined somewhere, just not in a std namespace.
C++ is notoriously hard to parse by tools.
Which is why I would recommend using Microsofts "Code Analysis" Tool, since you are using the Microsoft Compiler anyway.

Microsoft Visual Studio finds errors with all of my CUDA device-side functions

I was wondering if anyone can help with this error I'm getting in Cuda code. I want to define the function but it's saying that this declaration has no storage class or type specifier. Anyone know what should I do? This is a link to the screenshot of the error.
As #RobertCrovella explains, this is just your IDE not being aware of CUDA keywords when parsing your source.
Something you could do is make your parser find a
#define __device__
line, which would make it stop complaining. The problem is, you want the CUDA compiler not to hit this #define. So you can put it within an #ifdef, like so:
#ifdef __CUDACC__
#define __device__
#endif
which does the trick.
Of course, this only handles one keyword, __device__. You would need to have similar definitions for all CUDA keywords, as well as types and functions which are implicitly defined.

How do I find something that the C++ compiler thinks is defined as a constant?

I have the following errors reported when trying to build my application:
error C2143: syntax error : missing '}' before 'constant'
error C2143: syntax error : missing ';' before 'constant'
error C2059: syntax error : 'constant'
For the following code:
namespace oP
{
enum adjustment
{
AUTO_OFF,
AUTO_ONCE,
AUTO_CONTINUOUS,
AUTO_SEMI,
ABSOLUTE, // The line that the errors point to.
NUDGE
};
}
Lower case "absolute" builds ok, and if I misspell ABSOLUTE then it builds without errors.
I've searched my entire codebase and there's nowhere else using the term "ABSOLUTE".
I've investigated the built artifact without this change and I can't find any reference to ABSOLUTE in it.
Does anyone have pointers as to what's wrong or how to debug this?
Thanks
ABSOLUTE is #defined (to the number 1) in one of the windows API headers <windi.h>. That is what is confusing the compiler.
You could #undef it, remove <windows.h> if you don't need it, or rename your enumeration.
You've a macro defined in that name somewhere in one of your included files; check them. The easier way is to inspect the preprocessor's output.
If you use GCC, use the -E flag to stop after the preprocessing stage. With VC++ compiler you should be using /E and/or /P. See How do I see a C/C++ source file after preprocessing in Visual Studio? for details.
Usually the convention is to name macros in all uppercase; this is applicable to enumerations too, if you use C++03's (ordinary) enums. A better alternative is to use C++11's strongly-typed, scoped enumerations.
The name of each entry can be in Pascal case and with the enumeration's name decoration they become very readable Adjustment::Absolute as opposed to the older, unscoped enumeration's ABSOLUTE. This isn't very readable since the reader might confuse herself with the macro which wingdi.h declares (as Bathsheba points out). Apart from readability, it also avoids polluting the enclosing namespace.
Your are using visual c++ compiler and #include then you should get this error. In windows.h the file #include < wingdi.h> is included and in wingdi.h you will find
/* Coordinate Modes */
#define ABSOLUTE 1
#define RELATIVE 2
Hence error occurred.
How do I find something that the C++ compiler thinks is defined as a constant?
If your compiler is unwilling to produce helpful messages (usually it prints where term has been defined previously) or if you suspect that you fell victim of macro voodoo in WinAPI headers...
Selectively comment out lines of code and recompile to pinpoint the problem.
If you comment out one line and your program compiles after that, that line is source of your problem. If your code block is big, do "binary search" - comment out a whole block, then half of it, so you narrow down the problem quickly.
In IDEs you often can mouse over the item to see where it is defined or press a key or use context menus to "jump to definition".
In addition to that you can investigate preprocessor output.
and can't selectively comment out headers to test when it changes - since the new list of compiler warnings would be too onerous to work through
Make a blank *.cpp file and copy the problematic definitions into it till you break it. That would allow you to pinpoint the problem.
It is a good practice to always include only the minimal set of necessary headers into your own *.h files, preferably completely avoiding OS-specific headers, although that is not really possible in this case.
In your particular scenario another good option is to change your naming style for enum values. Normally ALL_UPPERCASE is reserved for macros only (macros definition and macro constants). A notable exception to this rule is the min and max macros defined within Windows headers (they can be disabled). Because you used it in an enum, you clashed with OS-specific definition. I would use the same naming convention for enums as for constant and local variables.

Calling a native function from managed code

I have a managed C++/CLI project which must use some native code. A simplified version of the native header file would be:
struct structA
{
// Some variables...
};
struct structB
{
// Some similar variables...
void convertTo(structA& dest);
};
This header is included in the managed code. The managed code has:
structA sA;
structB sB;
// Load data into sB...
sB.convertTo(sA);
I am using Visual Studio 2008 and compiling the managed code with /clr. This of course generates a linker error (LNK2028), as the implicit calling conventions differ. However I have been unable to use extern "C" declarations to solve this (or perhaps I'm using them wrong). I have tried several of the solutions provided to similar questions here, to no avail.
How do I correctly call the unmanaged function from the managed code? What declaration or wrapper is required here?
Turns out this was not a managed-unmanaged clash issue. I simply forgot to declare the used function as exported, i.e.,
__declspec(dllexport) void convertTo(structA& dest);
The second, more general linker error (LNK2019) for an unreferenced function was what I should have been paying attention to. It is strange that a managed-unmanaged clash error (LNK2028) was thrown as well, since this is a more specialized error (which also threw me off track). As far as I know, this error should only have applied was I to use /clr:pure, as was suggested in the comments as well.

MS Visual Studio 2010 C++ Preprocessor - If function is defined in macro with calls elsewhere, is there any overhead hit when undefined

I have a quick question, which I am sure has been asked so I do apologize if it is a duplicate. I tried searching google and stackoverflow but the results were unrelated to my question.
The scenario:
I have a Visual Studio 2010 project configuration that defines a preprocessor named DBG.
In the code, I have a #ifdef DBG section that declares a function signature in the header file (let's call it writeToFile) and defines that function within another #ifdef DBG/#endif section in the cpp file.
Throughout the rest of the project are calls to writeToFile.
The questions:
When the project is compiled under a different configuration (one that doesn't define DBG), how is this handled by the compiler? I know that the portions within the #ifdef/endif directives are pretty much ignored, but what happens to all the function calls to writeToFile? Does the compiler ignore these, too? Or during run time, do these calls actually occur and do nothing?
Thanks in advance
I suspect that the compiler should throw an error (undefined function writeToFile()). But you should be able to battle this by specifying #else section that defines the same function with an empty body. ie.
#ifdef DBG
void fun() { cout << "hello"; }
#else
void fun() { };
#endif //DBG
EDIT:
I personally would just define the function you want, and put the #ifdef/#endif block inside it's body.