warning when assert() modifies variables - c++

Is there anything I can do to get a compiler warning when one modifies a variable inside an assert() or a debug_print()?
I want to prevent mistakes like these from happening
int i=0;
assert((++i)); // i is modified only in debug mode
std::set<int> s;
debug_print(("item inserted: %d\n", s.insert(5).first )); // set is modified only in debug mode
Suppose I have set of wrapper functions that are built on debug mode only, where I can do the necessary checks
MyDbgAssert() // #define that wraps assert()
MyDbgPrint() // #define that wraps printf()

There are tools (e.g., Coverity) that detect side-effects in macros/assertions. CERT provides a list of such tools

Unit tests will detect this kind of error if you run them religiously on both debug and release builds.

Related

Is there a visual c++ predefined preprocessor macro that lets you know when the compiler is optimizing

I would like to be able to do something like this using visual c++ compiler (vc12):
// If we have compiled with O2
#ifdef _O2_FLAG_
bool debug_mode = false;
// If we are in dirty slow non optimized land
#else
bool debug_mode = true;
#endif
But I cannot find a predefined macro for this purpose.
Context:
The debug_mode flag is used like:
if (!debug_mode && search_timer->seconds_elapsed() > 20) {
return best_result_so_far;
}
The problem being that in a debug instance that I step through this constantly fails and bombs me out because strangely it takes me a lot longer to step through the code than the CPU normally goes through it :-)
If there is some underlying clock that pauses when debug does that would also solve my problem. Currently I am using the difference between two calls to std::chrono::high_res_clock::now().
EDIT:
In response to several comments explaining why I don't want to do what I want to do, I should perhaps reword the question as simply: Is there an equivalent of gcc's __optimize__ in cl?
You could use either _DEBUG or NDEBUG to detect the debug configuration. This technically doesn't mean the same thing as the optimization flag, but 99% of the time this should suffice.
Another option would be to add a preprocessor definition to the project yourself.

Code littered with asserts

Hi I am programming on some device.
There is some sample with such code:
Verify(SomeFunc(argc, argv) == SDK_OK);
Verify(SomeOtherFunction(&st_initialData) == SDK_OK);
Verify(SomeOtherFunction2(x,y) == SDK_OK);
In doc, Verify is defined as 'similar' to assert.
My question is: if I build my project in Release mode, what will happen with above statements? Will they lose their power? Will the Verify have any effect still?
To avoid possible problem with above, will I have to replace above codes with checking return values like this?:
if(SomeFunc(argc, argv) == SDK_OK)
{
// we are fine
}
else
{
// handle error somehow, such that it is also available in Release mode
}
It is impossible to say, as it seems that it is your project which implements Verify, as a macro or as a function. Why don't you take a look at the implementation?
That being said, MFC framework has VERIFY macro which is similar to ASSERT, with the distinction that the expression is always evaluated, even in release build, but doesn't do anything if result of the expression is false. This might be the similar approach, as your examples seem to call some functions which can affect the system state.
I assume you mean the MFC VERIFY macro or something very similar.
Using this macro is safe for release builds. The argument is executed in any case, just the macro itself does nothing in release.
In contrast to this, the ASSERT macro is completely skipped in release builds, so the "side effects" of the argument do not happen. Therefore, VERIFY is used if the argument is required for the actual program flow, and ASSERT is used when the argument is for asserting only.
Almost certainly you will not have to replace them. If your project wanted just to remove the calls in production compilation, it would probably have just plain assert directly. Try to read the source of the project (always a good idea) and understand what he macro does.

increase c++ code verbosity with macros

I'd like to have the possibility to increase the verbosity for debug purposes of my program. Of course I can do that using a switch/flag during runtime. But that can be very inefficient, due to all the 'if' statements I should add to my code.
So, I'd like to add a flag to be used during compilation in order to include optional, usually slow debug operations in my code, without affecting the performance/size of my program when not needed. here's an example:
/* code */
#ifdef _DEBUG_
/* do debug operations here
#endif
so, compiling with -D_DEBUG_ should do the trick. without it, that part won't be included in my program.
Another option (at least for i/o operations) would be to define at least an i/o function, like
#ifdef _DEBUG_
#define LOG(x) std::clog << x << std::endl;
#else
#define LOG(x)
#endif
However, I strongly suspect this probably isn't the cleanest way to do that. So, what would you do instead?
I prefer to use #ifdef with real functions so that the function has an empty body if _DEBUG_ is not defined:
void log(std::string x)
{
#ifdef _DEBUG_
std::cout << x << std::endl;
#endif
}
There are three big reasons for this preference:
When _DEBUG_ is not defined, the function definition is empty and any modern compiler will completely optimize out any call to that function (the definition should be visible inside that translation unit, of course).
The #ifdef guard only has to be applied to a small localized area of code, rather than every time you call log.
You do not need to use lots of macros, avoiding pollution of your code.
You can use macros to change implementation of the function (Like in sftrabbit's solution). That way, no empty places will be left in your code, and the compiler will optimize the "empty" calls away.
You can also use two distinct files for the debug and release implementation, and let your IDE/build script choose the appropriate one; this involves no #defines at all. Just remember the DRY rule and make the clean code reusable in debug scenario.
I would say that his actually is very dependent on the actual problem you are facing. Some problems will benefit more of the second solution, whilst the simple code might be better with simple defines.
Both snippets that you describe are correct ways of using conditional compilation to enable or disable the debugging through a compile-time switch. However, your assertion that checking the debug flags at runtime "can be very inefficient, due to all the 'if' statements I should add to my code" is mostly incorrect: in most practical cases a runtime check does not influence the speed of your program in a detectable way, so if keeping the runtime flag offers you potential advantages (e.g. turning the debugging on to diagnose a problem in production without recompiling) you should go for a run-time flag instead.
For the additional checks, I would rely on the assert (see the assert.h) which does exactly what you need: check when you compile in debug, no check when compiled for the release.
For the verbosity, a more C++ version of what you propose would use a simple Logger class with a boolean as template parameter. But the macro is fine as well if kept within the Logger class.
For commercial software, having SOME debug output that is available at runtime on customer sites is usually a valuable thing to have. I'm not saying everything has to be compiled into the final binary, but it's not at all unusual that customers do things to your code that you don't expect [or that causes the code to behave in ways that you don't expect]. Being able to tell the customer "Well, if you run myprog -v 2 -l logfile.txt and do you usual thing, then email me logfile.txt" is a very, very useful thing to have.
As long as the "if-statement to decide if we log or not" is not in the deepest, darkest jungle in peru, eh, I mean in the deepest nesting levels of your tight, performance critical loop, then it's rarely a problem to leave it in.
So, I personally tend to go for the "always there, not always enabled" approach. THat's not to say that I don't find myself adding some extra logging in the middle of my tight loops sometimes - only to remove it later on when the bug is fixed.
You can avoid the function-like macro when doing conditional compilation. Just define a regular or template function to do the logging and call it inside the:
#ifdef _DEBUG_
/* ... */
#endif
part of the code.
At least in the *Nix universe, the default define for this kind of thing is NDEBUG (read no-debug). If it is defined, your code should skip the debug code. I.e. you would do something like this:
#ifdef NDEBUG
inline void log(...) {}
#else
inline void log(...) { .... }
#endif
An example piece of code I use in my projects. This way, you can use variable argument list and if DEBUG flag is not set, related code is cleared out:
#ifdef DEBUG
#define PR_DEBUG(fmt, ...) \
PR_DEBUG(fmt, ...) printf("[DBG] %s: " fmt, __func__, ## __VA_ARGS__)
#else
#define PR_DEBUG(fmt, ...)
#endif
Usage:
#define DEBUG
<..>
ret = do_smth();
PR_DEBUG("some kind of code returned %d", ret);
Output:
[DBG] some_func: some kind of code returned 0
of course, printf() may be replaced by any output function you use. Furthermore, it can be easily modified so additional information, as for example time stamp, is automatically appended.
For me it depends from application to application.
I've had applications where I wanted to always log (for example, we had an application where in case of errors, clients would take all the logs of the application and send them to us for diagnostics). In such a case, the logging API should probably be based on functions (i.e. not macros) and always defined.
In cases when logging is not always necessary or you need to be able to completely disable it for performance/other reasons, you can define logging macros.
In that case I prefer a single-line macro like this:
#ifdef NDEBUG
#define LOGSTREAM /##/
#else
#define LOGSTREAM std::clog
// or
// #define LOGSTREAM std::ofstream("output.log", std::ios::out|std::ios::app)
#endif
client code:
LOG << "Initializing chipmunk feeding module ...\n";
//...
LOG << "Shutting down chipmunk feeding module ...\n";
It's just like any other feature.
My assumptions:
No global variables
System designed to interfaces
For whatever you want verbose output, create two implementations, one quiet, one verbose.
At application initialisation, choose the implementation you want.
It could be a logger, or a widget, or a memory manager, for example.
Obviously you don't want to duplicate code, so extract the minimum variation you want. If you know what the strategy pattern is, or the decorator pattern, these are the right direction. Follow the open closed principle.

assert() function not showing up in disassembly

My coworker just asked me to help on a problem, he has a few lines in his code as
for (long counter = 0; counter < End; )
{
...
assert(counter++ < MAX);
...
}
The problem is, when we use Visual Studio to debug line by line, seems the assert() line got skipped all the time, and counter never got incremented and thus the loop never finished.
When we look at the disassembly using VS, there is no assembly line for this assert() function. I never used assert() before, so I'm wondering is this normal and he shouldn't put any code behavior into assert() or something is wrong here with debugger or other?
Thanks.
Make sure that NDEBUG is not defined, as assert is enabled only in debug build, i.e when NDEBUG is not defined.
From here:
#ifdef NDEBUG
#define assert(condition) ((void)0)
#else
#define assert(condition) /*implementation defined*/
#endif
That is, when NDEBUG is defined, assert is no-op which is what you observe in assembly.
You should only use assert for debugging purposes.
The line
assert(counter++ < MAX);
contains logic, and it shouldn't.
In a non-debug build, it will never be executed.
assert is a macro, which is removed in release builds. So unless you're looking at a debug build, don't expect to see any assert code.
And because assert is a macro, and not a function, it's not likely to look like a single function call either.
If the code is built under Release Mode, the assert statements will not be included. Is your coworker using Release Mode?
Visual Studio's optimization settings may also remove the assert statements.
Couldn't your coworker change the for loop to not use the assert statement?
Asserts typically get removed from release builds and therefore are executed only for debug builds. You should never have any side effects affecting program logic in assert.

assertions in native c++ / debugging

example of using assertions during debugging:
char* append(char* pStr, const char* pAddStr)
{
// Verify non-null pointers
assert(pStr != nullptr);
assert(pAddStr != nullptr);
// Code to append pAddStr to pStr...
}
Calling the append() function with a null pointer argument in a simple program produced the following diagnostic message on my machine:
Assertion failed: pStr != nullptr, file c:\beginning visual c++ 2010\examples visual studio project files\tryassertion\tryassertion\tryassertion.cpp, line 10
I would like to know if assertions are neccesary. What is the point of using them if i can use if-else expressions to output my own error messages?
An assertion is a conditional check; it's just a macro that's something like this (simplified):
#define assert(b) if (!(b)) { std::cerr << ...; exit(1); }
I can think of two advantages:
When you compile in release mode (i.e. not in debug mode), then all the asserts will compile away to nothing, so you will incur no runtime overhead.
assert is an idiom; other programmers know to look for them, and they're also distinct from "normal" control flow.
assertions are used to ensure that certain basic assumptions are met. Basically you put in an assertation in every case which "couldnt possibly happen", most commonly assertions how the API has to be used e.g. preconditions and postconditions (like your example, which contains asserts which check the correct usage of your append function). For other errors, which are known to occur during runtime and which cannot be prevented beforehand (e.g. file-not-found or insufficient-permissions kind of errors), you will have to write error handling code.
Assertions are not included in release compilations, so they can only be used to catch critical programming errors, which will already occur in debug-mode test runs.
You should use assertions when the only case in which they are violated is an error in the program logic. You use normal if-then-else conditionals for things that may indeed happen because of input or external possible conditions (i.e. a file is missing).
When you know for sure that the program logic is faulty there is not really much sense in trying to continue execution... your program is working differently from what you think (because otherwise the assertion wouldn't have been triggered) and therefore the best option is just to yell what the problem is and die immediately.
Often assertion are removed when the code is compiled in "release" mode even if however it may make sense to keep them in place if the program logic is very complex and if continuing execution generating bad output is going to create bigger problems than stopping execution.
Note that a "trap" that sometimes novice programmers fall into with assertion is that when the assertion code is removed for release mode the expression inside the assert is not evaluated any more, and therefore if you program depends on side effects of that expression then you're going to be in trouble... for example:
...
assert(insert_record(db, data) == DB_OK); // <== this is bad
...
when assertion are defined away the insertion will not happen at all, leaving you with a program that doesn't work in release mode and that works instead when you try to debug the problem.