Concise and non-obtrusive error handling in C - c

Error handling in C code
#define CHECK_FOR_ERRORS(ret) \
if(ret != CY_U3P_SUCCESS) \
{ \
handleCriticalError(ret, __FILE__, __LINE__); \
}
Intended usage:
CHECK_FOR_ERRORS(CyU3PPibInit(CyTrue, &pibClock));
No return variables, no extra code lines, only wrapping important function calls with this macro.
But it doesn't work. The macro does not evaluate the function call, it only casts the function pointer to int.
How do I make this work?

You macro calls the function twice, first the actual call, and a call for error handling. Try this:
#define CHECK_FOR_ERRORS(ret) \
do { int r = ret; if (r != CY_U3P_SUCCESS) {\
handleCriticalError(r, __FILE__, __LINE__); \
} while(0)
You can see how the macro is interpreted with the -E flag of gcc, or a similar flag for your compiler. And in general, try to use each macro argument only once in the macro definition to prevent this kind of problems.

Personally I would do this much easier. Assuming CyU3PPibInit(CyTrue, &pibClock) initializes some library and returns 0 if successful. I would do something like the following:
if ( CyU3PPibInit(CyTrue, &pibClock) != 0){
fprintf(stderr, "At %s : %d: unable to load CyU3PPibInit, ", __FILE__, __LINE__);
/*eiter abort here or sets some variable that your subsequent program flow doesn't use this library */
}
/*continue without the library*/
this way you have simple to understand code. Marco substitution makes code usually difficult to read.

Related

assert macro implementation in C89, how to exit the program?

I'm trying to implement my own assert macro in a C89 standard.
I want it to be exactly as the original one:
dir/file.c:20: MyFunction: Assertion `null != pointer` failed.
There are 2 problems:
There is no option to print the function name because the pre identifier __FUNC__ is available only since c99 standard.
I don't know how to exit the program. I tried exit(1) and __Exit(1) but both of them are not working and I think it's because macros are converted to code while the per-processing stage, which means the pre-processor doesn't even know what are these exit functions yet. because they are relevant only in the compiler stage, right?
Here's my code:
/********************************* Inclusions *********************************/
#include <stdio.h> /* printf, NULL */
/***************************** Macros Definitions *****************************/
#define ASSERT(expr) \
if (!(expr)){ \
fprintf(stderr, "%s:%d: Assertion `%s` failed.\n" \
,__FILE__, __LINE__, #expr); }
/******************************************************************************/
int main()
{
void *null_ptr = NULL;
ASSERT(NULL != null_ptr);
printf("ALL WORKS");
return (0);
}
/******************************************************************************/
my output is:
`file.c:25: Assertion `NULL != null_ptr` failed.`
Is there any way to get the function name or exit the program with a macro?
Because right now, I'm not getting the function's name, and more important, the program isn't getting stopped even though the assert prints an error message.
And it's strange, because how it's not possible to get the function name or to exit a program with a macro but it is possible for the original assert to do both of these?
P.S the __FILE__ per-identifier prints for me only the file name, as file.c and not dir/file.c as the original assert does. Why is that?
I wish I could write something like:
#define ASSERT(expr) \
if (!(expr)){ \
fprintf(stderr, "%s:%d: %s: Assertion `%s` failed.\n" \
,__FILE__, __LINE__, __FUNC__, #expr); exit(1) }
Thanks.
Indeed, C89 doesn't have a way to get the function name. So if you can only rely on C89, you'll have to do without this. Note that many implementations may have provided their own extensions for this even before C99, and may have used those extensions in their own definitions of assert(); e.g. GCC had __FUNCTION__.
The standard assert() macro calls abort() if the assertion fails. So if you want to replicate its behavior, you can do the same.
Nate Eldredge answers most of your queries. In response to your P.S., I suspect it's something the compiler can internally do that we can't. Same with the function name but no __func__ (though GCC has a __FUNCTION__ macro that you can use).
You can still make your assert closer to the compiler assert though. That assert tries to emulate a function as best as possible. So for one, it has to work as an expression, which yours does not because of the if. Furthermore, it should return void. The man page on assert gives this "prototype":
void assert(scalar expression);
Both of these are possible. Here's an assert I just made right now that (I think) manages to meet both these requirements:
#define ASSERT(expr) \
((expr) ? \
(void) 0 : \
(void) (fprintf(stderr, "%s:%d: %s: Assertion `%s` failed\n", \
__FILE__, __LINE__, __FUNCTION__, #expr), abort()))
This makes use of the __FUNCTION__ GCC extension, you can remove that if you want to.

Better Assert in C

Sometimes I have to send the result of an assert over canbus, sometimes its local.
I use C only, Embitz compiler using GCC, STM32F407 or STM32F103.
My present assert is:
.h file:
extern char *astrbuf;
#define assert(left,operator,right)\
if(!((left) operator (right))) \
{asprintf(&astrbuf,"\nAssert error %s %d %ld %ld\n",__FILE__, __LINE__,\
(u32)(left),(u32)(right));\
asserted();\
}
.c file:
void asserted(void)
{ dprint("%s",astrbuf);
followed by the display code or canbus code.
Example:
assert(millis,<,maxtime);
This works very well, but will be better if the operator can be indicated.
I simply do not see how to display or send the operator, which can be ==, <, or >.
Why not use the standard assert interface and include the whole expression?
#define assert(EXPR) \
if (!(EXPR)) \
{asprintf(&astrbuf, "\nAssert error %s %d %s\n",__FILE__, __LINE__, #EXPR); \
asserted(); \
}
... using the # macro stringification operator.
By the way, why is half of your code in the macro and the other half in the asserted function? Why not do it all in one place?
#define assert(EXPR) \
if (!(EXPR)) \
{ \
asserted(__FILE__, __LINE__, #EXPR); \
}
with
void asserted(const char *file, int line, const char *expr) {
char *astrbuf;
asprintf(&astrbuf, "%s: %d: assertion failed: %s\n", file, line, expr);
dprint("%s", astrbuf);
...
}
Now you don't need a global variable anymore.
There's another potential issue. If you use your macro like this:
if (foo())
assert(x > 42);
else
bar();
... the else bar(); part will attach to the if statement hidden in assert, not the outer if. To fix this, you can wrap the whole thing in a do while loop:
#define assert(EXPR) \
do { \
if (!(EXPR)) { \
asserted(__FILE__, __LINE__, #EXPR); \
} \
} while (0)
Or alternatively make sure the whole macro expands to a single expression:
#define assert(EXPR) \
((void)((EXPR) || (asserted(__FILE__, __LINE__, #EXPR), 0)))
Of course you could also put the conditional logic in the function:
#define assert(EXPR) asserted(!!(EXPR), __FILE__, __LINE__, #expr)
void asserted(int cond, const char *file, int line, const char *expr) {
if (cond) {
return;
}
...
}
You can use the stringizing operator # to convert the macro parameter operator to a string #operator:
extern char *astrbuf;
#define assert(left,operator,right)\
if(!((left) operator (right))) \
{asprintf(&astrbuf,"\nAssert error %s %d %ld %s %ld\n",__FILE__, __LINE__,\
(u32)(left), #operator, (u32)(right));\
asserted();\
}
Perhaps you could try a slightly different approach to achieve the same goal.
Instead of passing (left, operator, right) into the macro, try passing a single boolean condition. You can use the condition inside of your actual assert function and also stringify it using macros. This way you can still report the whole condition to your debug module (canbus).
This will also work for more complicated expressions like ((a-b)< 0)
#define assert( condition ) custom_assert( condition , STRINGIFY_CONSTANT( condition ), __FILE__, __LINE__)
The stringify macro is in its own header file and was derived based on this link. https://gcc.gnu.org/onlinedocs/gcc-3.4.3/cpp/Stringification.html
#define STRINGIFY_CONSTANT(a) STRINGIFY_CONSTANT_DO_NOT_USE(a)
#define STRINGIFY_CONSTANT_DO_NOT_USE(a) #a
Obviously, don't use STRINGIFY_CONSTANT_DO_NOT_USE
void custom_assert( int condition , const char * condition_string, const char * file_name, int line_number)
{
if (!condition)
{
dprint("Assert Failed:'%s' File:'%s' Line:'%d'",condition_string, file_name, line_number);
}
}
I would avoid putting anything more than a single function call into your assert #define as that can be hard to debug and it will also increase the size of your code. I recommend putting any logic into the function.
I called my assert custom_assert. I also have many #defines to put the debug output to different channels like usb, rs232, a on screen display, etc. In release mode the asserts just reboot the embedded device, which is acceptable in my application.
Assert is a macro, the way I understand it, it is always inline.
The code for the machine has lots of asserts to prevent damage, therefore one needs to keep the code as fast as possible, ie. inline under normal circumstances.
When anything goes wrong, the function asserted is used, speed is no more a problem, safety is. The function asserted switches off motors, etc, and reports over canbus or local display. No way I want to do all that in a macro.
That is why part of the code is in a macro, part in a function.
Please correct me if my understanding is wrong.
Not having a global variable is a definite plus, and I have added the while (0), as in other macros.

is there a non-fatal equivalent to assert in c?

I would like to write assert statement but not abort the program. So perhaps use exact same syntax as assert() but called expect(). Of course I can write my own, but assert is quite clever (e.g. it knows not only the file and line number but even the expression which is not TRUE).
I could of course dig into the library and C-v/C-c a solution.
But this is such an obvious generic request I can't believe there is not a good solution already. Which should of course be easily found here...
It's because assert is a preprocessor macro, and so can use the __LINE__ and __FILE__ macros as the whole macro invocation is expanded into a single line.
You can easily make your own:
#define expect(value, message) \
do \
{ \
if (!(value)) \
{ \
fprintf(stderr, "%s failed in %s:%d\n", #value, __FILE__, __LINE__); \
} \
} while(0)
No, there are no such thing. However, it is quite easy to write it as :
#define expect( chk ) \
if (!(chk)) \
printf("Assertion (%s) failed %s at line %d ", #chk, __FILE__,__LINE__);
This test :
int main()
{
expect(0);
expect(1);
return 0;
}
is going to print the first failed assertion :
Assertion (0) failed t.c at line 8
Live demo.
With credit to BЈовић
#ifdef NDEBUG
#define expect(chk) ((void *)0)
#else
#define expect(chk) (chk ? (void) (0) : fprintf(stderr,"%s:%d %s: expectation (%s) failed.\n", __FILE__ , __LINE__ , __func__ , #chk))
#endif
This version
writes to stderr, not stdout
can be disabled like assert() with the NDEBUG macro
It looks as much like the assert() message as possible, though of course it doesn't have the flexibility that assert does in terms of other parameters.
I didn't see why forcing the use of a semicolon is useful - since if there is one it works, and if there isn't it still works!
Some cleverer solution like try...catch around assert() was my hoped for answer, though!

C-style assertion handlers

There are several ways to make dynamic checks in complex software:
assert.h implementation assert( expression_that_must_be_true );
Linux kernel style:
if (in_interrupt())
BUG();
If checked condition's value is not as expected, some bug handler is called.
For example:
#define BUG( ) \
{ \
printf("BUG found (function %s file %s line %d)\n", __FUNCTION__, \
__FILE__, __LINE__); \
exit(1); \
}
Even in this simplest implementation of bug handling some bugs can be hidden (as "there are no programs without bugs"). This bug can lead to recursive call of this bug handler (from printf, for example). If there are bug conditions still, bug handler will be called again and again, until stack is overflowed. In worst case, developer even will not see any messages (for example, if bug is in the beginning of printf).
Question is: What are good techniques of avoiding recursive calls in bug handlers, while still getting some debug information?
Initialize a global variable to the max depth to avoid recursive calls.
debug.c
unsigned Debug_MaxDepth = 5;
debug.h
#define BUG( ) \
{ \
if (Debug_MaxDepth > 0) { \
Debug_MaxDepth--;
printf("BUG found ...\n"); \
} \
exit(1); \
}

Detecting null parameter in preprocessor macro

I have the following macro function in vanilla C:
#define GLOG(format_string, ...) { \
const char *file = strrchr(__FILE__, '/'); \
char format[256] = "%s:%s!%d\t"; \
strncat(format, format_string, 248); \
strcat(format, "\n"); \
printf(format, __FUNCTION__, file ? file : __FILE__, __LINE__, ##__VA_ARGS__); \
}
which lets me print a debug message containing the current function, file and line number, e.g.
GLOG("count=%d", count);
might print
do_count:counter.c!123 count=456
How can I modify the function to print all local variables if caller omits format_string? e.g.
GLOG();
might print
do_count:counter.c!123 count=456, message="Hello world", array=[7, 8] structure={ptr=0xACE0FBA5E, coord={x=9, y=0}}
If that's not possible, how can I modify it to print just the current function, file and line number? e.g.
do_count:counter.c!123
As is, this returns an error:
error: expected expression before ‘,’ token
as the strncat line is simply
strncat(format, , 248);
First, inspecting all the local variables at runtime by the process itself seems impossible because C doesn't have any means for reflection.
Second, you would be much better off if you wrote the logging macro like that:
#include <stdio.h>
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define GLOGF(fmt, ...) \
printf("%s:%s " fmt "\n", __func__, __FILE__ "!" TOSTRING(__LINE__), ##__VA_ARGS__)
int main (void) {
/* main:test.c!xx count=5 */
GLOGF("count=%d", 5);
/* main:test.c!xx */
GLOGF();
return 0;
}
It is simpler and doesn't incur any additional runtime overhead since the string is concatenated at compile-time.
Also note that I have used __func__ instead of __FUNCTION__, because the latter is non-standard.
I found this link in this answer. It might help you with the first part of the question.
The second, how to get all local variables, is much harder, if not impossible. The reason is that the code, when compiled, doesn't actually have variables, it just have offsets into a memory area (the stack.) It might be possible that your compiler have internal functions that can be used to inspect the stack, but then you only have possible values not the names of the variables. The only solution I see it to use special pre-processor macros to declare local variables, and then a list of structures to represent them for introspection, which will be a lot of both runtime and memory overhead.
As others here have mentioned, C does not have reflection features, and therefore you are not going to be capable of capturing the local variables in a macro call. That being said, if you want something to conditionally happen with a macro depending on if there are or are not any arguments to the macro invocation (i.e., your "non-null" and "null" arguments), then you can do something like the following:
#include <string.h>
#define NULL_IDENT ""
#define IDENT(ident_name) #ident_name
#define MACRO(ident_name) \
if (strcmp(NULL_IDENT, IDENT(ident_name)) == 0) { \
/* add code for a null argument passed to the macro */ } \
else { \
/* add code for a non-null argument passed to the macro */ }
Based on Blagovest Buyukliev's answer, I've come up with the following solution for part 2:
#define GLOG(fmt, ...) do { const char *fn = strrchr(__FILE__, '/'); \
printf("%s:%s!%d\t"fmt"\n",__func__,fn?++fn:__FILE__,__LINE__,##__VA_ARGS__);\
} while(0)
using the preprocessor's string concatenation to simply concatenate a null string if the parameter is omitted.
Additionally, I added the do {...} while(0) to swallow the trailing semicolon so that the following if...else works:
if (...)
GLOG();
else
/* do something else */
(idea from http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html ).

Resources