assert() function not showing up in disassembly - c++

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.

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.

How to make robust assert?

I want to realize this behavior:
When program runs in debug mode, assert_robust(expression, commands) works strictly like classical assert(expression)
When program runs in release mode, assert_robust(expression, commands) perform some commands if expression is false
This can be done this way:
#ifdef NDEBUG
#define assert_robust(expression, command) if (!(expression)) command;
#else
#define assert_robust(expression, command) assert(expression);
#endif
And this can be used for example this way to make myfunction fault-tolerant:
char myfunction(const string& s, int i)
{
assert_robust(i >= 0, return '\0');
/* Normal code */
}
This work well, but how to make macro assert_robust that supports more than one (arbitrary) number of commands? (preferably by a standard C++ way)
And another question is:
Is it good thing to be strict in debug and benevolent in release?
EDIT: My idea why do such a thing is because it is practicaly much better if it is a bug in the program that the program maintains sometimes a little weird than when it crashes and user losing their data.
The more interesting question is the second:
Is it good thing to be strict in debug and benevolent in release?
My experiences is that it is a horrible idea to have different behavior in debug and release builds. You are signing up for issues in production that you will never be able to reproduce in a debug build because the behavior of the two is different.
Other than that, which you may claim won't be an issue if you assert in the first place in debug mode, asserts should be used to flag programming issues, situations from which you cannot recover safely. If you can recover safely in release mode, why assert in DEBUG? If you cannot, are you willing to fiddle with production data in a way you don't quite understand what it will do?
Without getting into the issue of if this is a good idea or not, you can use your macro to wrap multiple commands in a do-while(0); loop.
#ifdef NDEBUG
#define assert_robust(expression, command) if (!(expression)) \
do{command;} while(0)
#else
#define assert_robust(expression, command) assert(expression)
#endif
Note also that I did not include semicolons at the ends of the macros. If you include them in the macros, then something like
assert_robust(cond1, command1) /* no semicolon here, no problem */
assert_robust(cond2, command2) /* no semicolon here, no problem */
would be allowed, which would be really weird.
I don't think to use assertions this way is a good idea. Usually you use an assert, if you want the predicate to be always true, because its part of critical code. If its not true, than there is obviously a big problem and aborting is reasonable. But more and more people use assert like an ordinary error check for debugging. In this case its adequate to disable it completely in release mode. It think you should decide for one of this two approaches.
But if you want to run some kind of emergency commands before aborting, you could use the new lambda functions from C++11:
void ASSERT(int expression, std::function<void()> func) {
if(!expression) {
if (func) func();
abort();
}
}
You could use it like this:
ASSERT(a >= 0, []() { std::cerr << "ERROR" << std::endl;});
Or:
ASSERT(a >= 0, [this]() { this->terminate(); });
Or:
ASSERT(a >= 0, nullptr);

warning when assert() modifies variables

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.

Q_ASSERT release build semantics

I can't find a clear statement on the semantics of Q_ASSERT under release builds. If there is no assertion checking, then is the asserted expression evaluated at all?
Consider the following code
Q_ASSERT(do_something_report_false_if_failed());
Will do_something_report_false_if_failed() run under all potential Qt build configurations? Would it be safer (even though a bit more verbose and less readable) to do this instead:
bool is_ok = do_something_report_false_if_failed();
Q_ASSERT(is_ok)
The latter approach has the downside that ASSERT failures are less verbose, but perhaps it shows more clearly that the statement is executed?
The expression inside the Q_ASSERT will not be evaluated in non-debug build configurations.
Consider the source code below from the Qt repo.
#if !defined(Q_ASSERT)
# ifndef QT_NO_DEBUG
# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
# else
# define Q_ASSERT(cond) qt_noop()
# endif
#endif
If QT_NO_DEBUG is defined, then the entire Q_ASSERT statement is replaced with a qt_noop(), thereby removing any expression that it previously contained.
Never rely on any side effects created by an expression inside a Q_ASSERT statement. Technically it is still possible to ensure that QT_NO_DEBUG is not defined in a specific build configuration, but this is not a Good Idea™.
This seems to be different in Qt5.5 (but not earlier - see Qt5.4):
#if !defined(Q_ASSERT)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
# define Q_ASSERT(cond) do { } while ((false) && (cond))
# else
# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
# endif
#endif
I'm now getting lots of "​warning C4127: conditional expression is constant" in Visual Studio 2013.
Update:
Qt5.5 release notes say:
Q_ASSERT will now expand the condition even in release mode when
asserts are disabled, albeit in an unreachable code path. This
solves compiler warnings about variables and functions that were
unused in release mode because they were only used in assertions.
Unfortunately, codebases that hid those functions and variables
via #ifndef will need to remove the conditionals to compile with Qt 5.5.

Empty "release" ASSERT macro crashes program?

Take a look at this code:
#include <cassert>
#ifdef DEBUG
#define ASSERT(expr) assert(expr)
#else
#define ASSERT(expr)
#endif /* DEBUG */
The program will run only if I have DEBUG defined, otherwise it will hang and terminate with no results. I am using MinGW in Eclipse Indigo CDT. Advice is appreciated!
It's hard to tell without looking at the actual code that is causing the issue. My guess: you are evaluating an expression with side-effects within an ASSERT(). For instance, ASSERT( ++i < someotherthing ) whithin a loop. You could confirm by temporary modifying the macro definition to just expr on NDEBUG builds. After confirming this is the cause, go to each and every ASSERT call you are issuing to ensure that the expressions are side-effects free.
You are almost certainly abusing assertions. An assertion expression must never have side effects.
When you say, assert(initialize_critical_space_technology());, and then you omit this entire line in the release build, you can imagine for yourself what will happen.
The only safe and sane way to use assertions is on values:
const bool space_init = initialize_critical_space_technology();
assert(space_init);
Some people introduce a VERIFY macro for something that always executes the code:
#define VERIFY(x) (x) // release
#define VERIFY(x) (assert(x)) // debug