I am writing a large C program for inline use. Each module in this program has an init () function (for example, a constructor) for setting its own static variables.
The problem is that I have to remember to call all these init functions from main(). I also have to remember to return them if I somehow commented on them.
Is there anything clever to have all these functions invoked? Something like macro lines in every init function, which, after calling the function, check_inited()sends a warning to STDOUT if not all functions are called.
I could increase the counter, but I would need to maintain the correct number of init functions somewhere, and also error prone.
Thoughts?
Below is the solution I made, with the help of several users in this thread
My goal is to make sure that all of my init functions are actually called. I want to do this without saving lists or module counts across multiple files. I can't call them automatically, as Nick D suggested, because they need to be called in a specific order.
To do this, the macro included in each module uses the gcc attribute constructorto add the init function name to the global list.
Another macro, included in the body of the init function, updates the global list to make note that the function was actually called.
Finally, the check function is called in main()after all inits have completed.
Notes:
. ,
.
, .
"nx_lib". , "nxl".
, ,
.
. ,
.
static, , .
, , , , , .
:
pierr, constructor.
Nick D ## .
tod frye , .
.
nx_lib_public.h
#define NX_FUNC_RUN_CHECK_NAME_SIZE 20
typedef struct _nxl_function_element{
char func[NX_FUNC_RUN_CHECK_NAME_SIZE];
BOOL called;
} nxl_function_element;
void nxl_func_run_check_add(char *func_name);
BOOL nxl_func_run_check(void);
void nxl_func_run_check_hit(char *func_name);
#define NXL_FUNC_RUN_CHECK_ADD(function_name) \
void cons_ ## function_name() __attribute__((constructor)); \
void cons_ ## function_name() { nxl_func_run_check_add(#function_name); }
nxl_func_run_check.c
, .
#define MAX_CHECKED_FUNCTIONS 100
static nxl_function_element m_functions[MAX_CHECKED_FUNCTIONS];
static int m_func_cnt = 0;
void nxl_func_run_check_add(char *func_name)
{
if (m_func_cnt >= MAX_CHECKED_FUNCTIONS) {
print ("nxl_func_run_check_add failed, out of space\r\n");
return;
}
strncpy (m_functions[m_func_cnt].func, func_name,
NX_FUNC_RUN_CHECK_NAME_SIZE);
m_functions[m_func_cnt].func[NX_FUNC_RUN_CHECK_NAME_SIZE-1] = 0;
m_functions[m_func_cnt++].called = FALSE;
}
void nxl_func_run_check_hit(char *func_name)
{
int i;
for (i=0; i< m_func_cnt; i++) {
if (! strncmp(m_functions[i].func, func_name,
NX_FUNC_RUN_CHECK_NAME_SIZE)) {
m_functions[i].called = TRUE;
return;
}
}
print("nxl_func_run_check_hit(): error, unregistered function was hit\r\n");
}
BOOL nxl_func_run_check(void) {
int i;
BOOL success=TRUE;
for (i=0; i< m_func_cnt; i++) {
if (m_functions[i].called == FALSE) {
success = FALSE;
xil_printf("nxl_func_run_check error: %s() not called\r\n",
m_functions[i].func);
}
}
return success;
}
solo.c
,
#include "nx_lib_public.h"
NXL_FUNC_RUN_CHECK_ADD(solo_init)
void solo_init(void)
{
nxl_func_run_check_hit((char *) __func__);
}