Question

I know the words "portable" and "macro" don't often go together, but my code is generally riddled with #ifdef _DEBUG tags (I use VS2012) that confirm desired outcomes. I want to make my code portable to Unix systems.

My understanding, based on this post, is that Visual Studio uses _DEBUG and the C-standard uses NDEBUG, but that their functions are different (_DEBUG flags debug mode, NDEBUG flags assertions).

If I want my code to be as portable as possible, should I use #ifndef NDEBUG if I only ever want those lines of code to run when asserts are active? What are the consequences of this within Visual Studio? It seems to work but I want to make sure there's nothing I'm missing; ie. why would microsoft use _DEBUG when there's a perfectly good C-standard alternative? Historic reasons?

Was it helpful?

Solution 2

I don't know the real reason for MS not using the NDEBUG macro, and defining the _DEBUG instead. My my guess is that it is related to the definition of _ASSERT instead of assert.

The problem with assert() is that the C standard defines requires it to print a line to the console and abort the program. But Windows programs don't usually have a console, so MS thought that it would be nice to pop up a window instead. But that assert() pops up a window would not be standard compliant, so the developed a similar but different macro:_ASSERT, and a different macro to control its behavior: _DEBUG.

A similar mess exists with the _UNICODE and UNICODE macros, but that's another story...

Note that in the default configuration of a Visual C++ project, in debug mode _DEBUG is defined, but NDEBUG is not. While in release mode _DEBUG is not defined, but NDEBUG is. So for your own code, you can use any one of them. But naturally, if you want to be portable you should use NDEBUG, as the _DEBUG name is reserved to the compiler implementation.

OTHER TIPS

That ship sailed a long time ago, MSVC complied because resistance was futile. This works as you'd expect:

#ifdef NDEBUG
#pragma message("Release build selected")
#endif

That macro doesn't completely fall from the sky, like some do. Project + Properties, C/C++, Preprocessor, Preprocessor definitions setting. It works not because the compiler joined the Borg, the IDE did. Or to be a bit more specific, the project template did. A very good excuse :)

So no, making macros portable is completely not a problem. It only takes getting your makefile correct.

Albeit a bit contrived, you can do this to make it somewhat portable-er

#if defined(__unix__) && defined(NDEBUG)
#define _DEBUG
#endif

As far as I know, the only thing (by standard), NDEBUG should affect is assert macro. Therefore, if one wants to add their debugging facilities, he adds his own macro definitions like _DEBUG (which do not affect or depend on NDEBUG).

To make your debugging code portable, you're likely better off defining your own macro for the same purpose.

Then as an option, you could turn it on and off, say, depending on NDEBUG presence.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top