Calling function without parameters when the definition includes parameters - c

I'm trying to run an old MUD driver compiled with added -g flag and removed -O2 flag, so that I can debug it. I have a function with a prototype void try_to_swap(void), but the definition is void try_to_swap(volatile int* interrupted). Inside the function the value of that pointer is checked:
if(*interrupted)
...
The function is called without parameters, like the prototype - try_to_swap();
Everything works OK with the optimization flag. But without it I get a SIGSEGV when the function is called. The problem is that the pointer points to an address which is unreachable for the process (0x3b - every time), thus the segmentation fault.
My question is:
a) Why don't I get any errors during make? Shouldn't the lack of the parameter in the call be somehow noticed by the compiler?
b) During optimization, does the compiler somehow take care of the value of the pointer so the program won't crash?
c) What would be the right way to tackle this? Remove the pointer from definiton, add it to the prototype? The pointer is used only in this function, and only in mentioned if. It doesn't seem to be initialized anywhere. Or maybe it's somehow automatically initialized? I'm not too familiar with volatile pointers. But the pointer value is random garbage from the stack set before the function call, as no parameter value was provided. Is this even legal in C, where default values are not an option?

a) In C, () means "any arguments" and isn't the same as (void) which is no argument. try_to_swap() is valid but not a good documentation for users.
b) Yes, the compiler seems to detect the missing parameter and just passes a null pointer.
c) You could add the pointer argument to the prototype and pass what's required by the internal if or try a trick.

Related

C callbacks - optional argument?

Hey I have implemented some callbacks in my C program.
typedef void (*server_end_callback_t)(void *callbackArg);
then I have variable inside structure to store this callback
server->server_end_callback = on_sever_end;
What I have noticed it that I can pass in on_server_end callback function implementation that skips void *callbackArg and the code works correctly (no errors).
Is it correct to skip some arguments like void * implementing callback functions which prototypes takes such arguments?
void on_server_end(void) {
// some code goes here
}
I believe it is an undefined behavior from the C point of view, but it works because of the calling convention you are using.
For example, AMD64 ABI states that the first six arguments get passed to the calling function using CPU registers, not stack. So neither caller nor callee need no clean-up for the first six arguments and it works fine.
For more info please refer the Wikipedia.
The code works correctly because of the convention of passing arguments. Caller knows that callee expects some arguments - exactly one. So, it prepares the argument(s) (either in register or on stack - depending on ABI on your platform). Then callee uses those parameters or not. After return from callee, caller cleans up the stack if necessary. That's the mistery.
However, you shall not abuse this specific behaviour by passing incompatible function. It is a good practice to always compile your code with options -W -Wall -Werror (clang/gcc and compatible). Enabling such option would provide you a compilation error.
C allows a certain amount of playing fast and loose with function arguments. So
void (*fptr) ();
means "a pointer to a function which takes zero or more arguments". However this is for backwards compatibility, it's not wise to use it in new C code. The other way round
void (*fptr)(void *ptr)
{
/* don't use the void */
}
/* in another scope */
(*fptr)(); /* call with no arguments */
also works, as long as you don't use the void *, and I believe it is guaranteed to work though I'm not completely sure about that (on a modern machine the calling convention is to pass the first arguments in registers, so you just get a garbage register, and it will work). Again, it is a very bad idea to rely on it.
You can pass a void *, which you then cast to a structure of appropriate type containing as many arguments as you wish. That is a good idea and a sensible use of C's flexibility.
Is it correct to skip some arguments like void * implementing callback functions which prototypes takes such arguments?
No it is not. Any function with a given function declaration is not compatile with a function of a different function declaration. This rule applies for pointers to functions too.
So if you have a function such as pthread_create(..., my_callback, ...); and it expects you to pass a function pointer of type void* (*) (void*), then you cannot pass a function pointer of a different format. This invokes undefined behavior and compilers may generate incorrect code.
That being said, function pointer compatibility is a common non-standard extension on many systems. If the calling convention of the system is specified in a way that the function format doesn't matter, and the specific compiler port supports it, then such code might work just fine.
Such code is however not portable and not standard. It is best to avoid it whenever possible.

Use of (apparently) empty C function

Can anyone comment on the point of the following function, which appears to do not very much:
// Returns stored values
int getDetails(const int param1[],
int* param2,
int* param3,
int* param4)
{
(void)param1;
(void)param2;
(void)param3;
(void)param4;
return 0;
}
The comment is actually there with the code. I'm thinking it must be some kind of odd stub but it is being called and I'm racking my brains to try to imagine what I'm missing.
My best hunch so far is that the function has been deprecated but not removed and the (void)param is to avoid compiler warnings about unused variables.
Statements like (void)param1; are typically used to suppress warnings about unused function parameters. (As an aside, in C++ you could also comment out or remove the parameter names.)
You're correct that the function does nothing. If other code doesn't create a pointer to it, you could safely remove it.
It's an empty function. Casts to void suppress warnings about unused parameters.
Such functions are often used when a function must be called unconditionally or a valid function pointer must be provided, but really the function has nothing to do.
I have a few such functions in my compiler's code generator. There are two code generators actually, one for x86 and the other for MIPS. I compile and link one or the other, never both at the same time.
The code generators are different internally but have the same external API. So, some functions specific to one CPU have some work to do while the same functions for the other have nothing to do. Logically, some of them are empty since there's nothing to do.
My guess (opinion - sorry!) that it could be a stub as you say. If you have a function that takes one or more function pointers to achieve something and it does not allow for a NULL (don't bother with this) then you have to provide something for it to call.
The casts are probably to avoid the "unused parameter" warning.
You're right, it has no point.
All it does is explicitly ignore the arguments by evaluating them and casting the result to (void), and return 0.
Is the return value being used in the context of the call? The best approach is of course to remove the call and replace it with a 0 if the return value is being used, and test the program.
Some Compilers shows error/warning when you are not using the arguments passed to it , to avoid that mention that like it in your code . If the function is not called any where or not assigned to any function pointers , you can remove it as it is not doing anything specific

How does the warning of implicit declaration of any function affect my code ?

See I have made a library which has several .h & several .c files.
Now under some circumstances I have not removed a warning that says
warning: implicit declaration of function ‘getHandle’
Now I want to ask you, does this cause any problem in the binary of my library?
Will it negatively affect the execution of my library on embedded platforms or anywhere else?
In C90, a call to a function with no visible declaration creates an implicit declaration of a function returning int and taking the promoted types of the arguments. If your getHandle function returns a pointer, for example, then the compiler will generate code assuming that it returns an int. Assigning the result to a pointer object should at least trigger another warning. It might work ok (if int and the pointer type are the same size, and int and pointer function results are returned in the same way), or it could go badly wrong (if, for example, int is 32 bits and pointers are 64 bits, or if pointer results are returned in 68K-style address registers).
The C99 standard removed implicit int from the language. Calling a function with no visible declaration is a constraint violation, requiring a diagnostic and possibly causing your program to be rejected.
And if you just fix the problem, you don't have to waste time figuring out how and whether it will work if you don't fix it.
In such a case the compiler cannot verify that the usage of getHandle is proper - that is, whether the return value and the arguments are of the right type and count. It will just accept the way you call it without any explicit statement that this is the right way.
Adding a prototype of the function is a way to tell the compiler that this is the intended usage of the function and it will be a compile-time error not to comply to that.
It may cause some nasty bugs in case there is a mismatch between the way it's called and the way the function expects its arguments. The most likely effect will be a corruption of the stack.
If there isn't a mismatch, it won't make any difference at runtime.

Unknown C expression

I ran across the following line in an example program, and don't know what it is. I imagine it's a function call, but am not sure:
(void) pthread_mutex_init(&bottleneck, &mxattr);
If it is a function call, why is it preceded with (void)? I've never seen that before. Here's the line in more context:
attr_init(pthread_process, pthread_scope, stacksize);
(void) pthread_mutex_init(&bottleneck, &mxattr);
barrier_init(&setup_barrier, (2 * ntables) + 1);
Thanks for the help. The entire program is from this Solaris whitepaper (Appendix D)
It is a normal function call. The (void) part just indicates that the function returns a value and nothing will be done with it. To remove any warnings of about unused return values.
See casting unused return values to void.
POSIX Threads
The specific call - pthread_mutex_init - returns int. The cast to void is probably done to avoid specific warning about the return value being ignored during either compile time or a static code analysis.
Update: As #Jack Kelly commented on another answer, any good static analysis tool would simply ignore this cast and continue issuing the warning. Static analysis should be controlled through separate specific annotations, not by using language constructs that can affect the compiler output.
This is a function call with explicit casting of the result to void. This is just a development style to hint both compiler and those who read this code that function call is actually returning something that is intentionally ignored. In this example, pthread_mutex_init function returns integer. Some compilers will give you a warning if you call a function marked with warn_unused_result attribute.
Yes it is a function call. The function pthread_mutex_init() initializes a mutex used to prevent multiple threads clobberring some shared resource.
The function returns an int, the (void) is flagging that we are intentionally ignoring the return value. It stops the compiler complaining about unused return values.

Function pointer cast to different signature

I use a structure of function pointers to implement an interface for different backends. The signatures are very different, but the return values are almost all void, void * or int.
struct my_interface {
void (*func_a)(int i);
void *(*func_b)(const char *bla);
...
int (*func_z)(char foo);
};
But it is not required that a backends supports functions for every interface function. So I have two possibilities, first option is to check before every call if the pointer is unequal NULL. I don't like that very much, because of the readability and because I fear the performance impacts (I haven't measured it, however). The other option is to have a dummy function, for the rare cases an interface function doesn't exist.
Therefore I'd need a dummy function for every signature, I wonder if it is possible to have only one for the different return values. And cast it to the given signature.
#include <stdio.h>
int nothing(void) {return 0;}
typedef int (*cb_t)(int);
int main(void)
{
cb_t func;
int i;
func = (cb_t) nothing;
i = func(1);
printf("%d\n", i);
return 0;
}
I tested this code with gcc and it works. But is it sane? Or can it corrupt the stack or can it cause other problems?
EDIT: Thanks to all the answers, I learned now much about calling conventions, after a bit of further reading. And have now a much better understanding of what happens under the hood.
By the C specification, casting a function pointer results in undefined behavior. In fact, for a while, GCC 4.3 prereleases would return NULL whenever you casted a function pointer, perfectly valid by the spec, but they backed out that change before release because it broke lots of programs.
Assuming GCC continues doing what it does now, it will work fine with the default x86 calling convention (and most calling conventions on most architectures), but I wouldn't depend on it. Testing the function pointer against NULL at every callsite isn't much more expensive than a function call. If you really want, you may write a macro:
#define CALL_MAYBE(func, args...) do {if (func) (func)(## args);} while (0)
Or you could have a different dummy function for every signature, but I can understand that you'd like to avoid that.
Edit
Charles Bailey called me out on this, so I went and looked up the details (instead of relying on my holey memory). The C specification says
766 A pointer to a function of one type may be converted to a pointer to a function of another type and back again;
767 the result shall compare equal to the original pointer.
768 If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.
and GCC 4.2 prereleases (this was settled way before 4.3) was following these rules: the cast of a function pointer did not result in NULL, as I wrote, but attempting to call a function through a incompatible type, i.e.
func = (cb_t)nothing;
func(1);
from your example, would result in an abort. They changed back to the 4.1 behavior (allow but warn), partly because this change broke OpenSSL, but OpenSSL has been fixed in the meantime, and this is undefined behavior which the compiler is free to change at any time.
OpenSSL was only casting functions pointers to other function types taking and returning the same number of values of the same exact sizes, and this (assuming you're not dealing with floating-point) happens to be safe across all the platforms and calling conventions I know of. However, anything else is potentially unsafe.
I suspect you will get an undefined behaviour.
You can assign (with the proper cast) a pointer to function to another pointer to function with a different signature, but when you call it weird things may happen.
Your nothing() function takes no arguments, to the compiler this may mean that he can optimize the usage of the stack as there will be no arguments there. But here you call it with an argument, that is an unexpected situation and it may crash.
I can't find the proper point in the standard but I remember it says that you can cast function pointers but when you call the resulting function you have to do with the right prototype otherwise the behaviour is undefined.
As a side note, you should not compare a function pointer with a data pointer (like NULL) as thee pointers may belong to separate address spaces. There's an appendix in the C99 standard that allows this specific case but I don't think it's widely implemented. That said, on architecture where there is only one address space casting a function pointer to a data pointer or comparing it with NULL, will usually work.
You do run the risk of causing stack corruption. Having said that, if you declare the functions with extern "C" linkage (and/or __cdecl depending on your compiler), you may be able to get away with this. It would be similar then to the way a function such as printf() can take a variable number of arguments at the caller's discretion.
Whether this works or not in your current situation may also depend on the exact compiler options you are using. If you're using MSVC, then debug vs. release compile options may make a big difference.
It should be fine. Since the caller is responsible for cleaning up the stack after a call, it shouldn't leave anything extra on the stack. The callee (nothing() in this case) is ok since it wont try to use any parameters on the stack.
EDIT: this does assume cdecl calling conventions, which is usually the default for C.
As long as you can guarantee that you're making a call using a method that has the caller balance the stack rather than the callee (__cdecl). If you don't have a calling convention specified the global convention could be set to something else. (__stdcall or __fastcall) Both of which could lead to stack corruption.
This won't work unless you use implementation-specific/platform-specific stuff to force the correct calling convention. For some calling conventions the called function is responsible for cleaning up the stack, so they must know what's been pushed on.
I'd go for the check for NULL then call - I can't imagine it would have any impact on performance.
Computers can check for NULL about as fast as anything they do.
Casting a function pointer to NULL is explicitly not supported by the C standard. You're at the mercy of the compiler writer. It works OK on a lot of compilers.
It is one of the great annoyances of C that there is no equivalent of NULL or void* for function pointers.
If you really want your code to be bulletproof, you can declare your own nulls, but you need one for each function type. For example,
void void_int_NULL(int n) { (void)n; abort(); }
and then you can test
if (my_thing->func_a != void_int_NULL) my_thing->func_a(99);
Ugly, innit?

Resources