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!
Related
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.
my code:
#define DEBUG 3
#define TEST(...)
#if (DEBUG == 3) \
printf("%s: %s\n", __FILE__, __VA_ARGS__);
#endif
int main(void) {
TEST("TEST")
return 0;
}
Error: missing the binary operator before token 'printf'.
I don't understand what's the problem
You're trying to put the #if inside the macro, but C doesn't permit that kind of thing. The reason it's failing is the printf inside the #if is unexpected. This is a common request, but it's just not allowed.
However, you can accomplish the same thing by changing the way you do the test:
#include <stdio.h>
#define DEBUG 3
#if (DEBUG == 3)
# define TEST(...) printf("%s: %s\n", __FILE__, __VA_ARGS__);
#else
# define TEST(...)
#endif
int main(void) {
TEST("TEST")
return 0;
}
EDIT: Though test-type macros like this are common, this is not a great way to do it because it can lead to unhappy surprises in debug/nondebug situations.
What happens in this case?
if (something)
TEST("blah")
else
TEST("no")
This works as you expect in debug mode, but won't even compile in production because it devolves to if (something) else - it doesn't even have a closing semicolon. It's easy to find other examples that are much more devious.
Hiding a semicolon inside a macro like this is usually asking for trouble, so the better approach is to make them function-like where you have to provide the semicolon yourself, and the most obvious way to do it is:
# #define TEST(...) printf("%s: %s\n", __FILE__, __VA_ARGS__) // no semicolon
...
if (something)
TEST("blah");
else
TEST("no");
This is better and leads to less surprises, but it's still a little troublesome in that it can leave a dangling semicolon lying around, which some compilers object to.
A fix for this can be:
#if (DEBUG == 3)
# define TEST(...) printf("%s: %s\n", __FILE__, __VA_ARGS__)
#else
# define TEST(...) ((void)0) // dummy statement
#endif
which at least quiets the compiler. There are other approaches here too.
In C #define cannot "contain" #ifs
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.
I've found Zed Shaw's debug macros on his website when his C book "Learn C the Hard Way" was free to read. It was designed for Linux initially, and it works pretty well, been using it for a while.
Now, I've started to write C code for Windows and I'm using Visual Studio. I want to use these debug macros in a project I'm working on.
The problem is as follows:
Let's say I want to use the check macro to make sure a function returned without error.
display = al_create_display(640, 480);
check(display, "Failed to create display");
The definition for the macros that will be used are the following:
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
However, the problem I encountered was that Visual Studio marks strerror() as deprecated and aborts compilation. I plan on using threads in the project, so I don't want to go the "ignore" route, if possible.
What I did was I created a clean_errno() function that does the same thing as the macro, but uses a global buffer variable and calls strerror_s() to copy into it, then return a pointer to the log_err() macro.
However now I have to:
either create a brand new header and C file just for this one 3-liner function, which I think is just abundant
or I just declare and implement the function in the debug macro's header, which isn't considered good C practice at all, and also very ugly.
Is there any other trick/hack that I don't know of that would provide an elegant and simple solution to this?
Strerror is deprecated because it's not thread safe. If you don't care about this fact then you can probably find some option in VS to turn off this warning.
But it would be equally simple to implement a thread-safe version using sterror_s(). Remember, your macros can do more than just evaluate expressions, specifically it's completely possible to allocate a buffer in the macro:
#define check(A, M, ...) \
if(!(A)) { \
char _buffer[128]; \
strerror_s(_buffer, 128, errno); \
fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " (M) "\n", __FILE__, \
__LINE__, errno? _buffer : "None", ##__VA_ARGS__); \
errno = 0; \
goto error; \
}
I haven't tested this code so it may have some bugs, but it should be a start.
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.