Whats meaning of this rsAssert macro? - c++

i found this code from here
#if 1
#define rsAssert(v) do {if(!(v)) LOGE("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__);} while(0)
#else
#define rsAssert(v) while(0)
#endif
Question 1:
Here i am not getting why do and while is used here? Is there any special reason for using this?
Question 2:
What is the purpose of doing this all in macro. Why just one dont use assert() ?
i think perhaps there is a valid reason for this..

Your first question about why there's a do/while "loop" is covered here: What's the use of do while(0) when we define a macro?
The answer to the second question could be better answered by the code's author, but I guess they wanted to use their own logging system when an assert failed rather than the default one.

The do/while is a well-known trick for turning a block of statements into something that syntactically acts like a single statement. It allows use in places like:
if (whatever)
rsAssert(whatever);
else
// ...
whereas, most alternatives would produce a syntax error in this case.
As for why using it at all: because it writes output with LOGE instead of printing to stderr, and (unless LOGE does so) this doesn't seem to abort the program like assert will.

As asked many times before, the reason a do-while loop is use is for syntactic sugar:
// this line would be valid if a simple if was used:
rsAssert(myAssert)
// with a do-while, however, this is now invalid:
rsAssert(myAssert)
// so, that means you have to add the ';' to make it look like a function call:
rsAssert(myAssert);

Related

How to write safe and user friendly c/c++ #define macros

I have been thinking about how macros can be written to be safe, readable and intuitive. Proper use of them should be understood by the looks of them and when used incorrectly the compiler should tell you, and not let you introduce an obscure bug.
When writing multiple line define macros I usually find myself constructing them like this to fullfill the desired criteria:
#define macro(x) do{ \
... some code line ; \
... some code line ; \
}while(0)
This way you can both...
if (a)
{
macro(a);
}
and...
if (a)
macro(a);
else
{
...
}
A nice feature of this is that if you use them incorrectly you will get a compiler error. This will not compile for example:
if (a)
macro(a)
else
b();
However, I have seen SW developers read this kind of macro construct and getting quite perplexed by it. Can you think of alternative ways to write macros that will not deceive the user in a way where they do something other than expected, and still are quite understandable when browsing a new piece of code?
Also, can you find any problems with the do {} while(0) method? It could for example be a situation where you would expect the macro to behave a certain way and where this is not the case.
The reason why i am not completely convinced the do {} while(0) method is good practice is that the macros themselves look a bit weird and take some explaining to anyone (some at least) who has not seen the construct before.
Edit:
Here is an example from one of the links in the comments (thanks!) that i like. It's quite readable I think:
#define MYMACRO(a,b) \
if (xyzzy) asdf(); \
else (void)0
Is it possible to break it?
A common approach when you want your macro to do nothing, and toggle this behavior with the preprocessor, is to use the void(0) operation.
#if SOMETHINGS
#define macro(x) do{ \
... some code line ; \
... some code line ; \
}while(0)
#else
#define macro(x) ((void)(0))
#endif
This way you won't break compilation whenever nulling out macro operations

Asserts and unused variables in Visual Studio 2010 SP1

I use the code below for assert in "release", have for some time with no issues ever.
Then along came Visual Studio 2010 Pro SP1, and things went south, as also happened to mr. Krunthar.
Problem is, when I have a piece of code in which I do sanity checks like this:
#define ASSERT(condition, msg) do { (void)sizeof(condition); } while (0,0)
// Note: (0,0) is to avoid warning C4127: conditional expression is constant
{
int result = CallMeOnce(); // its side effects are the important stuff
// perform additional sanity checks in debug
ASSERT(result >= 0, "too low");
ASSERT(result <= 100, "too high");
ASSERT(!isPrime(result), "too prime");
}
VS2010 spits out a warning C4189: 'result' : local variable is initialized but not referenced
I am at a loss on how to fix that:
Code like (void)(condition) will execute any expression passed as condition, which is a no no
Putting CallMeOnce() inside the ASSERT expression is impossible
Refactoring all the different CallMeOnce()s is NOT an option
I'd rather not have to write scaffolding code like (void)result, if (result == result) {} or UNREFERENCED_PARAMETER(result) (or equivalent) outside the macro just to avoid the warning as it makes the code even harder to read (pollution), and is easy to forget while writing code in Debug. Also: in lots of places!
I'm considering creating another macro (ASSERTU?) just for variables, but it feels so... quirky!
Has anyone found a better way out?
Thanks a lot!
Edit: Clarified preference for the variable handling at caller's level
in your assert macro you have
(void)sizeof(condition);
presumably this code was written by someone else, so, explanation:
the rôle of the (void) cast is to tell the compiler that you really intended this do-nothing expression statement to do nothing.
now do the same for your result
that was easy, wasn't it? sometimes solution is just staring you in the face. ;-)
by the way, when this construct is used to suppress warnings about unused formal arguments, you might want to add a redefinition of the name, like
(void) unusedArg; struct unusedArg;
this prevents inadvertently using the argument with later maintenance of the code
however, the error generated by visual c++ is not exactly informative
there are umpteen level of sophistication that can be added, but i think even the name redefinition is perhaps going too far – the cost greater than the advantage, perhaps
You can use the UNREFERENCED_PARAMETER macro.
It seems I got somewhere!
#define ASSERT(condition, msg) \
do { \
if (0,0) { \
(void)(condition); \
} \
} while (0,0)
Mandatory explanation:
(void)(condition); will suppress C4189, but will execute any expression or function call passed in.
However, if (false) {...} will make sure that whatever (valid expression) "..." may be, it will not be executed. Code optimization phase will see it as dead code and throw it away (no code generated at all for the block in my tests!).
Finally, the owl trick (0,0) will prevent C4127, which seems a quite useless warning in the first place but hey, less clutter in the compilation output!
The only weakness I could find to this solution is that condition needs to be compilable code, so if you #ifdef-ed out part of the expression, it will raise an error. It might be that it's also compiling (though not calling) the code for the called functions; more research would be useful.
This is much nicer. Also: an expression instead of a statement
#define ASSERT(condition, msg) ( false ? (void)(condition) : (void)0 )
though you might want both debug and release versions of your assert to have the same semantic, so a do {...} while (0,0) around it might be appropriate.
You can use pairs of __pragma(warning(push)) __pragma(warning(disable: 4127)) and __pragma(warning(pop)) to silence C4127 just for the ASSERT line.
Then (void)(true ? (void)0 : ((void)(expression))) silences C4189.
This is an excerpt from my own implementation of an assertion macro.
The PPK_ASSERT(expression) macro will ultimately expand to PPK_ASSERT_3(level, expression) or PPK_ASSERT_UNUSED(expression) depending on whether assertions are enabled or disabled.
#define PPK_ASSERT_3(level, expression, ...)\
__pragma(warning(push))\
__pragma(warning(disable: 4127))\
do\
{\
static bool _ignore = false;\
if (PPK_ASSERT_LIKELY(expression) || _ignore || pempek::assert::implementation::ignoreAllAsserts());\
else\
{\
if (pempek::assert::implementation::handleAssert(PPK_ASSERT_FILE, PPK_ASSERT_LINE, PPK_ASSERT_FUNCTION, #expression, level, _ignore, __VA_ARGS__) == pempek::assert::implementation::AssertAction::Break)\
PPK_ASSERT_DEBUG_BREAK();\
}\
}\
while (false)\
__pragma(warning(pop))
and
#define PPK_ASSERT_UNUSED(expression) (void)(true ? (void)0 : ((void)(expression)))

Is it possible to make the execution of a program skip fprintf-statements/How to create my own fprintf-function?

In my C++-code there are several fprintf-statements, which I have used for debugging. Since I might need them again, I would prefer not to comment them out for the moment.
However, I need the execution of the program to be fast, so I would like to avoid them being printed out, as they are for the moment (I redirected stderr to a file).
Preferably this would be determined by the user passing an argument to the program, which I would extract like this:
main (int argc, char *argv[])
{
int isPrint=0;
if (argc > 1 ) {
isPrint = atoi ( argv[2]);
}
}
I thought of renaming fprintf to another name, and then from that function do a fprintf-call using the same parameters, based on the value of isPrint; however, then I realized that fprintf can have so many different kind of arguments and a various number of arguments; and that I don't know any generic way of declaring my own function with those requirements.
So I wonder how to create a function,which works exactly like fprintf, but which takes the extra parameter isPrint; or how to solve the above problem in another way.
Complementary information after first post:
One solution would be to add this before each fprintf-statement:
if (isPrint == true )
The typical approach is to use the preprocessor to compile away the calls to fprintf().
You would do something like this:
#if defined DEBUG
#define LOG(a) fprintf a
#else
#define LOG(a)
#endif
And in the code you would do:
LOG(("The value is %f", some_variable));
Note the double parenthesis, that's just to make the syntax work. You can do it nicer, but this is simpler to explain.
Now, you would either just edit the code to #define or #undef the DEBUG preprocessor symbol at the top of the file, or pass suitable options to the compiler (-D for GCC).
First note that if this is just for debugging, I'd agree that the typical way is to use macros or preprocessor defines to tell the compiler to include logging or not.
However, if you don't want it removed entirely by the compiler (so that you can turn the printing on or off with an argument), you could write your own log function that takes isPrint and some string, and then use snprintf() to format the string before you call it.
Something along these lines:
void myLog(int isPrint, char *message)
{
if(isPrint == 1)
{
fprintf(logFile, "%s", message);
}
}
char msg[64];
snprintf(msg, 64, "Test Message %d", 10);
myLog(isPrint, msg);
It may also be possible to wrap fprintf() in your own varags function, but that would be more complicated.
For debugging purpose you can use the variable argument macro:
#ifdef DEBUG
#define FPRINTF(...) fprintf(__VA_ARGS__)
#else
#define FPRINTF(...)
#endif
Be attentive that, if you use fprintf directly instead of FPRINTF then since you are defining a library function, it should appear after #include<> of that function.
It depends how much flexibilty you've got in changing the code and whether you want to be able to switch this off at runtime or just compile time.
I'd suggest you wrap it in your own variadic function (for tips look here) and then you've encapsulated the functionality.
Your function will essentially be just a thin wrapper round fprintf() but at this point you can then either use the preprocessor to ensure that your logging function does nothing if you compile it out, or you can do an integer comparison with, say, a logging level at runtime so that the underlying fprintf() only gets called if your debugging level is high enough.

Get return type of function in macro (C++)

I have ASSERT(x) macro and I want to call return if it asserts (in release configuration).
To do this I need to know return type of function where I use this ASSERT. How to get it (I deal with C++03, LLVM GCC 4.2 compiler)?
My ASSERT macro:
#define ASSERT(x) \
if(!(x)) {
LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
return /*return_type()*/; \
}
PS: I tried return 0; - compiler shows error for void functions (and I didn't try it for complex returning types), if return; - error for non-void functions.
(Updated...)
I'll answer to werewindle, nyarlathotep and jdv-Jan de Vaan here. I use standard assert for debug configuration. But after beta-testing I still get crash reports from final customers, and in most cases I need to change my crashing functions:
ASSERT (_some_condition_);
if (!_some_condition_) // add this return
return _default_value_;
I understand, that my program may crash probably later (otherwise it will definitely crash in current function). Also I can't quit application because developing is for iPhone (apps may not quit programmatically there). So the easiest way would be to "auto return" when assertion failed.
You can't determine the return type of the surrounding function in a Macro; macros are expanded by the preprocessor, which doesn't have this kind of information about the surroundings where these macros occur; it is basically just "searching and replacing" the macros. You would have to write separate macros for each return type.
But why not exit the program (i.e. calling the exit function)? Just returning from a function doesn't seem like a very robust error handling. Failed assertions should after all only occur when something is terribly wrong (meaning the program is in a state it was not designed to handle), so it is best to quit the program as soon as possible.
There are no proper way to determine return type inside a function in C.
Also, if you somehow implement your variant of ASSERT it will lead to erroneous program behavior. Main idea of ASSERT: if it fails, then program is in undefined state and only proper way is to stop it now. I.e. by calling exit().
i think you can do this with a template function, that you call default(x) from within the macro.
template<class T> default<T>(T x) { return T(); }
that will work for everyting with a default constructor. I think you need to write a special macro for void.
I hope i got the template syntax right, my c++ is getting rusty.
You can't do that, the C/C++ preprocessor is pretty basic and it can't do any code analysis. At most what you can do is pass the return type to the macro.
But here's my opinion: you're using assertions the wrong way. They should only be used for sanity checks of the code (for errors than can only happen because of the programmer); if all assertions pass, you don't need to care about them, you don't need to log them.
And not only that, but (in general) you should employ the element of least surprise. Do you expect ASSERT to log something and then forcefully make the function return? I know I wouldn't. I either expect it to close the application completely (what the standard assert does) or let me decide what happens next (maybe I have some pointers to free).
Macros do not return values, as they are no functions per se. They substitute the source code where they are used, so you'd return in the function where the macro is used.
There is no way to get the return value from a macro.
You could just define another macro for your needs.
#define ASSERT(x) \
if(!(x)) { \
LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
ASSERT_DEFAULT_RETURN(); \
}
And then inside a function:
int foo(){
#ifdef ASSERT_DEFAULT_RETURN
#undef ASSERT_DEFAULT_RETURN
#endif
#define ASSERT_DEFAULT_RETURN() return 0
// ...
ASSERT(some_expression);
// ...
// cleanup
#undef ASSERT_DEFAULT_RETURN
}
Just do this
#define ASSERT(x, ret, type) \
if(!(x)){
LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
return (type) ret;
}
I believe you are trying to solve the wrong problem. You don't want your program to crash in case of assertions, you best improve your testing.
Having a 'return' in these assertions give you a false sense of security. Instead it hides your problems and causes unexpected behavior in your program so the bugs you do get are much more complex. A colleague of mine actually wrote a good blog post about it.
If you really would want it, you could try writing return {}; so it default constructs the value, or have an assert macro where you also provide the failure case. However I really don't recommend it!

Finding statement pattern in c++ file

I have a macro that looks like this:
#define coutError if (VERBOSITY_SETTING >= VERBOSITY_ERROR) ods()
where ods() is a class that behaves similarly to cout, and VERBOSITY_SETTING is a global variable. There are a few of these for different verbosity settings, and it allows the code to look something like this:
if (someErrorCondition)
{
// ... do things relating to the error condition ...
coutError << "Error condition occurred";
}
And there is functionality in this framework to set the verbosity, etc. However, the obvious pattern breaks when not using braces in something like this:
void LightSwitch::TurnOn()
{
if (!PowerToSwitch)
coutError << "No power!";
else
SwitchOn = true;
}
because of the macro, will turn into this:
void LightSwitch::TurnOn()
{
if (!PowerToSwitch)
if (VERBOSITY_SETTING >= VERBOSITY_ERROR)
ods() << "No power!";
else
SwitchOn = true;
}
Which is not the intended functionality of the if statement.
Now, I understand a way to fix this macro properly so it doesn't cause this problem, but I'd like to run an audit on the code and find any place that has this pattern of "if (...) coutError << ...; else" to find out if there are any other cases where this happens to make sure that when fixing the macro, it will indeed be correct functionality.
I can use any language/tool to find this, I just want to know the best way of doing that.
You could try - temporarily - modifying the macro to something like this, and see what doesn't compile...
#define coutError {} if (VERBOSITY_SETTING >= VERBOSITY_ERROR) ods()
The 'else' clauses should now give errors.
Don't bother trying to find all of the locations in your code where a logic error is occurring -- fix the problem at its source! Change the macro so that there's no possibility of error:
#define coutError if(VERBOSITY_SETTING < VERBOSITY_ERROR); else ods()
Note that what I've done here is inverted the test, added an empty statement for the then clause, and put the output object in the else clause. This still allows you to use << foo << bar after the macro, and if you have a trailing else clause belonging to a different if statement, it will get matched up properly, since it expands like so:
if(foo)
coutError << bar;
else
baz();
becomes
if(foo)
if(VERBOSITY_SETTING < VERBOSITY_ERROR)
;
else
ods() << bar;
else
baz();
I think all good usages of the macro are preceeded with '{' or ';'.
So try this regular expression:
[^{;]\s*coutError
You'll need to turn on multi-line matching and search against entire files.
You might need to grab more stuff so that you can locate the line in question :-)
Alternatively changing the macro is a neat idea, if we can work out something that will fail correctly. Maybe a block followed by the conditional operator:
#define coutError {} (VERBOSITY_SETTING >= VERBOSITY_ERROR)?(ods()):(nullstream())
(But does require implementing a nullstream() operator.)
(Alternatively get rid of the conditional entirely temporarily - as you suggest is a comment to another answer #Roddy (currently the selected answer)).
p.s. I know you didn't ask, but an easy way to wrap the macro to make it safe is with a do {} while(false) loop.
I see in your comments above that you're thinking of using a template in the macro, and I can't comment yet (I'm 9 points short of it), so...
What stops you from doing
#define CoutError(s) { if (VERBOSITY_SETTING >= VERBOSITY_ERROR){ ods(s); } }
And then
void LightSwitch::TurnOn()
{
if (!PowerToSwitch)
CoutError("No power!");
else
SwitchOn = true;
}
And redefine ods to admit a string, or alternatively if you can't, then just define an OdsHelper function which takes a string and whose body is simply ods << inString?
I wouldn't play with macros trying to mimic the << syntax if there is no clear gain. At least with macros simulating the function syntax we're more used and we know we have to write the blocks to prevent strange issues.
Do you really need the << syntax?
And do you really need to introduce a template for this simple behaviour?
Oh and one last thing - don't use macros.
I think the real problem is the use of the macro - not the code that gets preprocessed. But I don't think this is the answer you are looking for.
I would find a way to do it without using macros at all - and if you do use conditional compiles you can do so in the call to ods() - depending on some #define it can use whatever functionality you want.
just my $.02
regular expression search?