I am developing my own assert function in C, and is is declared in my header file as:
void Certify_Continuity( const char* expression, const int line, const char* file );
It should be called using a macro defined as:
#if !defined ( ENABLE_DEBUG ) || defined ( __CALLE__ )
#define DEBUG_ASSERT( e ) (void)(e)
#else
#define DEBUG_ASSERT( e ) ( e ) ? (void)0 : Certify_Continuity( #e, __LINE__, __FILE__ )
#endif
The problem here is that the programmers are able to call Certify_Continuity directly.
Is there any technique to disallow the user to call the function directly, allowing him only to call it using the macro?
A macro is just textual (token) substitution performed before the compiler proper runs, so you can't prevent someone from just manually expanding the macro and removing the parts they don't like.
However, you can make it arbitrarily difficult and dangerous for someone to do this. For example, you can omit the declaration of Certify_Continuity from the header file, and just declare it inline like this:
#define DEBUG_ASSERT(e) do { \
extern void Certify_Continuity( const char* expression, const int line, const char* file ); \
if(!(e)) Certify_Continuity(#e, __LINE__, __FILE__); \
} while(0)
This way, anyone who calls the function directly has to declare the prototype first.
You can also name it in such a way that others will think twice about calling it:
void DO_NOT_CALL__USE_DEBUG_ASSERT__Certify_Continuity(...)
Of course, if someone is determined enough to bypass you, and doesn't care about the crazy wart sticking out of their code, then that's their problem. If they work for or alongside you, that's when you use externalities like code review to block this behaviour.
You could use the trick in C that (foo)() calls the function foo, whereas foo() expands the macro foo (under the assumption that both exists).
In you case, your macro should look like:
#if !defined ( ENABLE_DEBUG ) || defined ( __CALLE__ )
#define DEBUG_ASSERT( e ) (void)(e)
#else
#define DEBUG_ASSERT( e ) ( e ) ? (void)0 : (Certify_Continuity)( #e, __LINE__, __FILE__ )
#endif
#define Certify_Continuity(x,y,z) YOU_SHOULD_NOT_CALL_Certify_Continuity()
If the user tries to call Certify_Continuity directly, an error is issued that YOU_SHOULD_NOT_CALL_Certify_Continuity doesn't exist.
Of course, this can't prevent the user from calling it like (Certify_Continuity)().
Related
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 have a log library that uses a macro to trace a message. This macro makes use of predefined macros like __func__ and __PRETTY_FUNCTION__ to indicate in which function/method the message was logged.
The macro of my log library is defined in the main header of my log library, outside any function.
For some reason, the preprocessed code contains __func__ (or __PRETTY_FUNCTION__ if i'm using this one) litterally, just like if these predefined macros didn't exist. But i know they DO exist because if i'm using them without using my lib's trace macro, they work !
Here is my libs macro :
#if _MSC_VER >= 1400 // If >= VS2005
#define _TRACE_FUNC_SIGNATURE __FUNCSIG__
#elif defined(__ANDROID__) || defined( __GNUC__ ) && defined( __cplusplus ) // If G++ and/or Android NDK
#define _TRACE_FUNC_SIGNATURE __func__
#else
#error // Unsupported compiler
#endif
// Forces the reprocessing of x to properly expand __VA_ARGS__ when using MSVC compiler
#define _TRACE_REPROCESS( x ) x
#define _TRACE_X( _methodName_, _logCatPtr_, ... ) \
do { \
::dbg::LogCategory * const _catPtrVal_ = (::dbg::LogCategory *)(_logCatPtr_); \
if( NULL != _catPtrVal_ && _catPtrVal_->IsEnabled() ) \
{ \
_TRACE_REPROCESS( _catPtrVal_->_methodName_( _TRACE_FUNC_SIGNATURE " - " __VA_ARGS__ ); ) \
} \
} while( false )
#define TRACE_E( _logCatPtr_, ... ) _TRACE_X( Error, _logCatPtr_, __VA_ARGS__ )
#define TRACE_W( _logCatPtr_, ... ) _TRACE_X( Warning, _logCatPtr_, __VA_ARGS__ )
#define TRACE_I( _logCatPtr_, ... ) _TRACE_X( Info, _logCatPtr_, __VA_ARGS__ )
I know that these macros have no reason to be defined outside a function, but since i'm only using my trace macro inside functions/methods, then it should be defined there !
I'm using the default Android NDK compiler provided with eclipse, which as I read is some kind of extended G++.
EDIT : If I replace __func__ by an actual string litteral, it works, no syntax error. This lets me think that __func__ is definately not defined when used in my macro.
In some implementations, __func__ is a variable, not a macro (at least in gcc). So, you cannot use it as if it were a string literal.
So, this :
_TRACE_REPROCESS( _catPtrVal_->_methodName_( _TRACE_FUNC_SIGNATURE " - " __VA_ARGS__ ); )
will have to be written differently. I don't know how _catPtrVal_->_methodName_ is implemented, but if it can take multiple parameters, then something like this will probably do the trick :
_TRACE_REPROCESS( _catPtrVal_->_methodName_( _TRACE_FUNC_SIGNATURE, " - " __VA_ARGS__ ); )
If not, then you'll have to use some other way of concatenating __func__ with the rest of the log line (using a std::stringstream eg.).
More details
The C standard specifies __func__ like this :
The identifier __func__ shall be implicitly declared by the translator as if,
immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function.
Ie. it leaves it up to the implementation whether to provide it as a variable, or a macro (as long as it behaves as if it were defined as shown above).
As an example, gcc provides it as a variable, and MSVC provides it as a macro.
I thought I'd add my two cents - it IS possible to use the function signature in preprocessor directives, but you have to capture it first. Here's an example working up to a comparison of __PRETTY_FUNCTION__ and the preprocessor alternative.
#include <stdio.h>
#define CAT(X,Y) X ## Y
#define VAR(X) X
#define VAR_(X) VAR(X)
#define VAL(X) #X
#define VAL_(X) VAL(X)
/* Alias for constexpr cstring */
#define SZ const char*
#define CE_SZ constexpr SZ
/* Alias for assignment with appended log statement */
#define LOG(X, Y) X = Y; CE_SZ VAR_(CAT(INFO_, X)) = \
VAL_(X) " = " VAL_(Y) " (" __FILE__ VAL_(:__LINE__) ")"
/* SZ_A has no preprocessor value */
CE_SZ SZ_A = "Value of SZ_A";
/* SZ_B only has value to the preprocessor during LOG
(no define from inside a define, macro, etc.) */
CE_SZ LOG(SZ_B, "Value of SZ_B");
/* SZ_C has a global preprocessor name and value, but no compile time name */
#define SZ_C "Value of SZ_C"
/* SZ_D associates a compile time name with the value of SZ_C */
CE_SZ LOG(SZ_D, SZ_C);
/*
__PRETTY_FUNCTION__ and __func__ don't expand to string literals, but
to references to strings initialized by the compiler. If you capture the
signature in a preprocessor define, it's available globally; if you pass
it to a preprocessor macro, it's available within the scope of the macro.
__PRETTY_FUNCTION__ depends on compiler implementation (if it's defined
at all) - parameter names will be missing, template typenames and values
will be enumerated, etc.
*/
#define SIG template<typename T = SZ> void test(T caller)
SIG {
/* int main(int, const char**) */
printf(" Called function: %s\n", caller);
/* void test(T) [with T = const char*] */
printf(" Current function: %s\n", __PRETTY_FUNCTION__);
/* template<typename T = const char*> void test(T caller) */
printf(" Preprocessor signature: " VAL_(SIG) "\n");
}
CE_SZ LOG(SZ_E, VAL_(SIG));
int main(int argc, const char *argv[]) {
/* SZ_A = "Value of SZ_A" */
printf("%s = \"%s\"\n", VAL_(SZ_A), SZ_A);
/* SZ_B = "Value of SZ_B" (main.cpp:26) */
printf("%s\n", INFO_SZ_B);
/* SZ_C = "Value of SZ_C" */
printf("%s\n", "SZ_C = " VAL_(SZ_C));
/* SZ_D = "Value of SZ_D" (main.cpp:32) */
printf("%s\n\n", INFO_SZ_D);
test(__PRETTY_FUNCTION__);
/* SZ_E = "template..." (main.cpp:53) */
printf("\n%s\n", INFO_SZ_E);
}
I want to implement cross-platform build of my DLL with mingw32/VC.
At the moment everything is perfect with mingw side. However I have to wrap several things in macro for VC (it is built as /TC), for example:
void __attribute__((fastcall)) do1 ( A*, B , C, D );
bool __attribute__((fastcall)) ( *do2 ) ( E*, F );
The first one is simple, just a macro:
#ifdef __MINGW32__
#define __FASTCALL__ __attribute__((fastcall))
#elif _MSC_VER
#define __FASTCALL__ __fastcall
#else
#error "unsupported compiler"
#endif
The problem comes with the second one. Calling convention with a function pointer should looks like
bool ( __fastcall *do2 ) ( E*, F );
I tried the following macro (I skipped ifdef part):
#define __FASTCALLP__(func) (__attribute__((fastcall))(*##func))
#define __FASTCALLP__(func) (__fastcall *##func)
or if pass function name with asterisk:
#define __FASTCALLP__(func) (__attribute__((fastcall))(##func))
#define __FASTCALLP__(func) (__fastcall ##func)
Both failed with
error: pasting "*" and "function_name" does not give a valid
preprocessing token
May I wrong at my approach at all? Or I have to ifdef the whole code blocks or separate it to different files?
The problem is with the Concatenation-Operator ##. It will produce a new preprocessor token by concatenating the left- and right-hand-side, which does not exists (*do2 is no defined token)
Simply omit it and write like this (omitting #ifdefs):
#define __FASTCALL__(func) (__attribute__((fastcall))(func))
#define __FASTCALL__(func) (__fastcall func)
and use like this:
bool __FASTCALL__(do1)(A*, B , C, D);
bool __FASTCALL__(*do2)(E*, F);
Currently, I have a scenario much like this:
#define my_macro(var) __builtin_types_compatible_p(typeof(var), foo) ? do_something : do_something_else
However, inadvertently the macro gets passed this parameter:
my_macro(int x);
Which of course fails, because typeof(int x) isn't valid.
Is there a transformation I can apply inside the my_macro which will allow typeof to work on that expression? I cannot change what is passed into the macro, only what happens inside the macro.
So, something like this:
#define my_macro(var) typeof(?? var ??)
Or, is there another expression I should be using here?
Well, I found a way to do it, using yet another GCC extension, this time the statement expression:
#define my_typeof(definition) typeof(({ definition, _def; _def; }))
Which, of course, expands to:
typeof(({ int x, _def; _def; }))
Pretty ugly, but why do I care? It works.
You could handle x or int x separately but to handle both with one macro you would need the ability to parse/separate a space-delimited argument within the C preprocessor. To my knowledge, no such support exists in the C preprocessor. Without such parsing capabilities you must find some other clever way to write a macro that works around this limitation, for example, something in the spirit of my_macro2() in the following code sample:
#include <stdio.h>
#define my_macro1(var) \
do { \
typeof(var) blah; \
printf("sizeof(var)=%d\n", sizeof(blah)); \
} while(0)
#define my_macro2(var) \
do { \
var, newvar_sametype; \
typeof(newvar_sametype) blah; \
printf("sizeof(newvar_sametype)=%d\n", sizeof(blah)); \
} while(0)
int
main()
{
int x;
my_macro1(x);
my_macro2(char y);
return 0;
}
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 ).