I have following code in C:
pthread_cleanup_push(pthread_mutex_unlock, &mutex);
however when I compile it, I get the following warning:
warning: initialization from incompatible pointer type
What's wrong? It looks like the cleanup handler should return void*, not int. Is there any way to bypass this warning without writing additional wrapper?
The expression pthread_mutex_unlock does not have type void (*)(void *). You need to wrap it:
static void cleanup_unlock_mutex(void *p)
{
pthread_mutex_unlock(p);
}
and pass this function's address to pthread_cleanup_push.
Others may advise you to just cast pthread_mutex_unlock, but this is incorrect and unsafe. It will cause the function to be called via a pointer to the wrong function type, resulting in undefined behavior.
Related
In some C project, I have seen this code:
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud;
(void)osize;
/* some code not using `ud` or `osize` */
return ptr;
}
Do the two casts to void serve any purpose?
It is there to avoid warnings from the compiler because some parameters are unused.
The reason for having unused parameters in the prototype is usually because the function needs to conform to some external API - perhaps it is a library function, or a pointer to that function is passed to another function that expects this calling convention. However not all arguments used by the calling convention are actually needed in the function itself.
The reason for mentioning the parameter name in the body is to avoid warnings like
unused.c: In function ‘l_alloc’:
unused.c:3:22: warning: unused parameter ‘ud’ [-Wunused-parameter]
void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
^~
This warning can be suppressed with using the actual parameter in the function body. For example if you do have the following statement:
ud;
This warning is now suppressed. However now GCC will produce another warning:
unused.c:5:5: warning: statement with no effect [-Wunused-value]
ud;
^~
This warning tells that the statement ud;, while being syntactically valid C, does not affect anything at all, and is possibly a mistake, not unlike the statement
abort;
which should perhaps have been written as abort(); instead for it to do something.
And that's where the (void) cast comes in - it will tell the compiler unambiguously and explicitly that the statement is supposed to have absolutely no effect at all.
So I have the following function, evidently a void:
static void *CpuStatsTestLoop (void *arg){
UNUSED (arg);
rtems_object_set_name(rtems_task_self(), "CPU Usage Thread");
while (1)
{
sleep (CPU_USAGE_REPORT_INTERVAL_SECS);
rtems_cpu_usage_report();
rtems_cpu_usage_reset();
}
}
and it throws
"cpu_stats.c:98:1: warning: no return statement in function returning non-void [-Wreturn-type]".
I've tried adding a blank return and return 0 with no luck.
Any idea about why it's throwing this error, and how to fix?
This is not a void function, this is a void* (void pointer) function. It must return a value, which must be a pointer to data of any type, or NULL.
In your case, a return is not necessary, because the function never returns: it has a while(1) loop, which runs forever. A better approach is to make it a void function, rather than a void* function, unless it must conform to some predefined function pointer type.
If changing return type is not an option, for example, because you must pass this function as a start_routine parameter of pthread_create you can silence the warning by adding return NULL at the end of the function's body.
This function has a return type of void *, i.e. a pointer of any type, not void, so it must return a value.
You could fix this by changing the return type to void. However, it looks like this function is meant to be invoked as a thread, in which case it has to have a signature of void *(*)(void *), so if that's the case changing the return type is not an option.
Given that this function has a while (1) loop it should never return. Still, the function needs to return something, so put return NULL; at the bottom. That will satisfy the compiler, and it will act as a safety catch in case you later introduce a bug that causes you to break out of the loop.
I'm having getting the above warning and understand it, but just don't know how to fix it. My code is below, but basically what I'm doing is storing a function pointer in a struct, and initializing the struct in another function that I call from my main. The code seems to compile when I use it with a default function (i.e. free()) but not when I use it with the test_func function below. Thoughts?
Struct:
typedef struct my_struct {
my_type **double_pointed;
int num;
void (*funcp)(void *data);
} my_struct_t;
Init function:
my_struct_t *init(int num, void (*my_funcp)(void *data)) {
// unimportant code to the problem, but basically just some mallocs for the other data
my_struct_t *my_str;
my_str->funcp = my_funcp;
return struct;
}
function I want to point to:
void desired_func(my_type *obj) {}
my call to the init func:
init(5, desired_func);
full error:
incompatible pointer types assigning to 'void (*)(void *)' from
'void (my_type *)'
on the line in the init function above:
my_struct_t *my_str;
my_str->funcp = my_funcp;
Change the function pointer types to match the function, ie. :
void (*funcp)(my_type *data);
If you want to be able to use functions with different signatures (eg. different parameter types), you can add explicit casts. For example :
init(5, (void (*)(void*)) desired_func);
Note that any time the desired_func function (or any other function whose signature doesn't match the funcp function pointer) needs to be called through the function pointer, the function pointer will have to be cast back to its original type (void (*)(my_type*) in this case) before calling the function, or it invokes undefined behavior.
Another (somewhat better) alternative is to change the desired_func definition like this :
void desired_func(void *vobj) {
my_type* obj = vobj;
/* rest of the code */
}
Note that when calling desired_func (through a function pointer or directly), the type of the object whose address is passed as parameter needs to be my_type, or dereferencing obj inside the function (and if alignment differs even the cast itself) will invoke undefined behavior.
The added complexity for dealing with the potential for undefined behavior when casting (as noted above) means that I would advise against casting - needing such casts is probably indicative of a problem in your design. Ie. there's probably a better solution if you think about your requirements a bit more.
gcc version 4.3.3 under Ubuntu Linux 9.04 in case that is relevant.
This is the offending code:
pthread_cleanup_push(ctl_cleanup, NULL);
with ctl_cleanup() defined as
void* ctl_cleanup(void *arg);
There are other instances where this warning pops up, in similar circumstances. The warning also appears if I call something like
pthread_cleanup_push(pthread_mutex_unlock, (void *)&m);
where m is of type pthread_mutex_t. The warning reads:
warning: initialization from incompatible pointer type
I don't understand. I've passed other things around using void pointers (e.g. when passing arguments to a pthread) without that warning. Can someone help me out?
void ctl_cleanup(void *arg);
The above is the prototype you are looking for. It returns void, not a pointer to void.
The extra * in the function is because it takes a pointer to a function taking one void* argument returning void.
In some C project, I have seen this code:
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud;
(void)osize;
/* some code not using `ud` or `osize` */
return ptr;
}
Do the two casts to void serve any purpose?
It is there to avoid warnings from the compiler because some parameters are unused.
The reason for having unused parameters in the prototype is usually because the function needs to conform to some external API - perhaps it is a library function, or a pointer to that function is passed to another function that expects this calling convention. However not all arguments used by the calling convention are actually needed in the function itself.
The reason for mentioning the parameter name in the body is to avoid warnings like
unused.c: In function ‘l_alloc’:
unused.c:3:22: warning: unused parameter ‘ud’ [-Wunused-parameter]
void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
^~
This warning can be suppressed with using the actual parameter in the function body. For example if you do have the following statement:
ud;
This warning is now suppressed. However now GCC will produce another warning:
unused.c:5:5: warning: statement with no effect [-Wunused-value]
ud;
^~
This warning tells that the statement ud;, while being syntactically valid C, does not affect anything at all, and is possibly a mistake, not unlike the statement
abort;
which should perhaps have been written as abort(); instead for it to do something.
And that's where the (void) cast comes in - it will tell the compiler unambiguously and explicitly that the statement is supposed to have absolutely no effect at all.