I am developing a thread pool in c language and i wanted to allow a task to have an arbitrary number of arguments. Even-thought i could use a function like
int (*task) ();
This function would be able to be called with any type of arguments, like for example i could do
int fib(int n) { return n < 2 ? n : fib(n-1) + fib(n-2); }
...
task = fib;
printf("fib(10)=%d\n",task(10));
However what I want is to be able to save the arguments to run it later, without having to use a call to malloc, because otherwise i would prefer to just use a task like
void * (*task) (void *);
in which i would only have to save the void * argument on a struct.
However i wanted to do that for arbitrary arguments, is it possible to make it automatically for any kind of functions i want, without even using any va_list.
Is it possible?
tx in advance
I'm afraid what you want is not possible - given I correctly understand your question.
The way I'd implement it is using an anonymous pointer to a struct, which implementation is known by the callback and by the caller, but not the thread pool, which will only carry around a single pointer.
But, sadly that solution implies using a malloc(), or nasty memory copy on preallocated space which could be on the stack or globally.
If it was only the argument, then I'd use:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
typedef void *(*task_t)();
#pragma GCC diagnostic pop
But that won't work for return types.
The 1st #pragma makes GCC remember which -W flags were provided on the command line. The current warning flags get pushed on a stack.
The 2nd #pragma makes GCC not whine about the absence of the arguments.
The 3rd #pragma restores the old warnings.
The ‘#pragma’ directive is the method specified by the C standard for providing additional information to the compiler, beyond what is conveyed in the language itself.
— https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html
Related
Does below function need any stack for execution?
int a;
void func(void)
{
a = 10;
}
As long as a C compiler can see the definition of func, it can1 implement func without using any stack space. For example, where it sees a call to func, it can implement that by emitting an instruction or two to move 10 into a. That would achieve the same result as calling func as a subroutine, so the C rules permit a C implementation to implement a call to func in that way, and it does not use any stack space.
Generally, if the compiler could not see the definition of func, as when compiling another source file that calls func but does not define it, the compiler would have to issue a call instruction or something similar, and that would, at the least, push the return address onto the stack.
Additionally, if the routine being called were more complicated, the compiler might choose not to implement it inline or might not be able to do so. (For example, if func contained calls to itself, it is generally not possible for the compiler to implement it with inline code in all situations; the compiler will need to implement it with actual subroutine call instructions, which do use stack space.)
Footnote
1 Whether any particular compiler will implement func without using stack space is another matter, dependent on the compiler, the switches used to compile, and other factors.
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.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm interested in creating my own implementation of a doubly-linked list in C. The goal is to make it as flexible and "user" friendly as possible. This means it can't be restricted to one type of data. I'd also like to minimize memory management outside of the list code. That is, I want the list code to handle allocating and freeing any necessary memory. (But, of course, the list could be used to store pointers to dynamically-allocated data.)
I'm using two structs. The "node" struct holds pointers to the node immediately before it and the node immediately following it, a void* pointer to the data it contains, and the size of the data. However, because this is C, it can't hold the type of data. The "list" struct keeps track of the beginning and end of the list, the number of elements in the list, and so on. I've already implemented the functions for initializing the list and appending data to the list. The memory allocation and deallocation and linking seem to be working fine, and the lists appear to link to one another properly. The problem is how to actually import the data when creating a list node. Here are the approaches I've considered:
Passing a pointer to the data through a void* and the size as another argument. This could be made more user-friendly by adding a macro to take the address and size of a variable and pass those to the function. The problem? Not everything I might want to add to the list can have its address taken. For example, consider list_append(list, 17). This should add a new node with an integer payload of value 17 to the end of the list, but it would not work because the integer literal 17 can't have its address taken.
Passing the size of the data as one argument and the data itself on the call stack as an extra argument. C supports arguments of unknown number, type, and size though the .../stdarg.h method. I figured I could use a macro to take the sizeof() the item being appended and pass this along with the item itself to the appending function. The problem here is that the varargs macros want me to specify a type (not just the size of the type). So, I did some digging and found that GCC apparently uses the __builtin_next_arg macro to implement variable arguments in stdarg.h. Obviously, this would make my code dependent on GCC (or, at least, on this particular macro), but it might work at least with this particular compiler. The __builtin_next_arg macro allegedly gives the address of the argument following the last named one on the argument list as a void*. When I tried this approach on Windows (using MinGW 32-bit), it worked as intended. A simple memcpy() from the value given by __builtin_next_arg to the newly allocated buffer copied the data. However, when I used GCC 64-bit on Ubuntu, all hell broke loose. __builtin_next_arg was giving me addresses very far from where I'd expect the argument to be. The compiler also started occasionally complaining about the second argument to va_start wasn't the last argument in the list, despite the fact that I don't even use va_start in my code at all. Also, no matter what I did, the values I seemed to be getting were zeros (NULL, 0).
Is there a way I could fix this? What I basically want is a version of va_arg that gives the address of the argument on the stack. Other approaches are also acceptable.
In C++, I would be able to use templates to avoid this problem entirely, but I want to use C.
I would recommend you either not use __builtin_* functions at all or thoroughly study their implementations by reading the docs/gcc sources/asm compiler output of simple functions you code just to see how it works.
First, the behavior of specifically __builtin_next_arg could be completely different between mingw and linux environment because of different ABI in use.
Next, the __builtin_* function(s) may be superseded by another one(s) in a different gcc version. For example, in gcc-4.8.3 (linux build, to be precise) va_* macroses are implemented using
__builtin_va_start(), __builtin_va_end() and __builtin_va_arg() functions and there is no occurrences of __builtin_next_arg in the gcc internal header files.
No, you cannot use the __builtin_next_arg here. The reason is that even with __builtin_next_arg and such, your called function must know the type of data.
And no, function arguments are not stored on stack in say Linux x86-64 ABI; the first 6 arguments are provided in registers. And the registers depend on their types, so float and int are in different register, even though both are of size 4. Sorry, you just cannot do it like this, even in a particular GCC version on this ABI.
However if you're using C11, you can use a macro, that uses static_assert to assert the sizeof object passed in; then you can use some _Generic tricks to store different types into a struct that contains char contents[sizeof val];, something like:
#include <assert.h>
#include <string.h>
#define VALUE_SIZE (sizeof(int))
struct list;
struct value_type {
char contents[VALUE_SIZE];
};
int _list_append(struct list *l, struct value_type v);
struct value_type coerce_float(float arg) {
struct value_type rv;
memcpy(&arg, rv.contents, sizeof arg);
return rv;
}
struct value_type coerce_int(int arg) {
struct value_type rv;
memcpy(&arg, rv.contents, sizeof arg);
return rv;
}
static_assert(sizeof(float) == VALUE_SIZE,
"code relies on float and int being of the same size");
#define coerce_arg(X) (_Generic((X), \
float: coerce_float, \
int: coerce_int, \
void*: coerce_int \
)((int)X))
#define list_append(L, X) _list_append(L, coerce_arg(X))
list_append(l, 4);
list_append(l, 4.0f);
list_append(l, (void*)0); // will throw an error since it is not supported
This is quite portable, but note that for example MSVC compiler does not even support C99. GCC and LLVM shouldn't have problems. However on the con side, you must add each supported compatible type by hand. Including each pointer type, or cast your pointers to say (void*).
If you're ok with using only GCC I believe you can write a macro that uses typeof to make a variable of the exact argument type, then memcpy its contents directly into this struct.
Is there a way to check for buffer overflows in VLA's ? I used -fstack-protector-all -Wstack-protector but get these warnings:
warning: not protecting local variables: variable length buffer
Is there a library for achieving this ? (-lefence is for heap memory)
I'm currently using Valgrind and gdb.
You can use -fmudflap instead of -fstack-protector-all
Update: Some documentation and options are here http://gcc.gnu.org/wiki/Mudflap_Pointer_Debugging
Perhaps using alloca() will help. That's annoying, because c99 should save you from having to use it, but the GCC man page seems to say that the stack protection code will be turned on if you use alloca().
Of course the real solution is to write perfect, bug free code that never tries to corrupt the stack.
I don't see how a library could do this for you; with a variable-length array, you're not calling any functions to do the indexing, so there's no place to "hook in" a library. With malloc(), the allocation is explicit in a function and you can track it.
Of course, you could go through the code and use preprocessor trickery to add some macro to each indexing point, and have the macro expand to code that checks the boundaries. But that is very intrusive.
I'm thinking something like changing:
void work(int n)
{
int data[n]; /* Our variable-length array. */
data[0] = 0;
}
into something like:
#include "vla-tracking.h"
void work(int n)
{
VLA_NEW(int, data, n); /* Our variable-length array. */
VLA_SET(data, 0, 0);
}
Then come up with suitable macro definitions (and auxiliary code) to track the accesses. As I said, it won't be pretty. Of course, the idea is that the macros would be able to "compile out" to just the plain definitions, controlled by some build-time setting (debug/release mode, or whatever).
How does the compiler know the prototype of sleep function or even printf function, when I did not include any header file in the first place?
Moreover, if I specify sleep(1,1,"xyz") or any arbitrary number of arguments, the compiler still compiles it.
But the strange thing is that gcc is able to find the definition of this function at link time, I don't understand how is this possible, because actual sleep() function takes a single argument only, but our program mentioned three arguments.
/********************************/
int main()
{
short int i;
for(i = 0; i<5; i++)
{
printf("%d",i);`print("code sample");`
sleep(1);
}
return 0;
}
Lacking a more specific prototype, the compiler will assume that the function returns int and takes whatever number of arguments you provide.
Depending on the CPU architecture arguments can be passed in registers (for example, a0 through a3 on MIPS) or by pushing them onto the stack as in the original x86 calling convention. In either case, passing extra arguments is harmless. The called function won't use the registers passed in nor reference the extra arguments on the stack, but nothing bad happens.
Passing in fewer arguments is more problematic. The called function will use whatever garbage happened to be in the appropriate register or stack location, and hijinks may ensue.
In classic C, you don't need a prototype to call a function. The compiler will infer that the function returns an int and takes a unknown number of parameters. This may work on some architectures, but it will fail if the function returns something other than int, like a structure, or if there are any parameter conversions.
In your example, sleep is seen and the compiler assumes a prototype like
int sleep();
Note that the argument list is empty. In C, this is NOT the same as void. This actually means "unknown". If you were writing K&R C code, you could have unknown parameters through code like
int sleep(t)
int t;
{
/* do something with t */
}
This is all dangerous, especially on some embedded chips where the way parameters are passed for a unprototyped function differs from one with a prototype.
Note: prototypes aren't needed for linking. Usually, the linker automatically links with a C runtime library like glibc on Linux. The association between your use of sleep and the code that implements it happens at link time long after the source code has been processed.
I'd suggest that you use the feature of your compiler to require prototypes to avoid problems like this. With GCC, it's the -Wstrict-prototypes command line argument. In the CodeWarrior tools, it was the "Require Prototypes" flag in the C/C++ Compiler panel.
C will guess int for unknown types. So, it probably thinks sleep has this prototype:
int sleep(int);
As for giving multiple parameters and linking...I'm not sure. That does surprise me. If that really worked, then what happened at run-time?
This is to do with something called 'K & R C' and 'ANSI C'.
In good old K & R C, if something is not declared, it is assumed to be int.
So any thing that looks like a function call, but not declared as function
will automatically take return value of 'int' and argument types depending
on the actuall call.
However people later figured out that this can be very bad sometimes. So
several compilers added warning. C++ made this error. I think gcc has some
flag ( -ansic or -pedantic? ) , which make this condition an error.
So, In a nutshell, this is historical baggage.
Other answers cover the probable mechanics (all guesses as compiler not specified).
The issue that you have is that your compiler and linker have not been set to enable every possible error and warning. For any new project there is (virtually) no excuse for not doing so. for legacy projects more excuse - but should strive to enable as many as possible
Depends on the compiler, but with gcc (for example, since that's the one you referred to), some of the standard (both C and POSIX) functions have builtin "compiler intrinsics". This means that the compiler library shipped with your compiler (libgcc in this case) contains an implementation of the function. The compiler will allow an implicit declaration (i.e., using the function without a header), and the linker will find the implementation in the compiler library because you're probably using the compiler as a linker front-end.
Try compiling your objects with the '-c' flag (compile only, no link), and then link them directly using the linker. You will find that you get the linker errors you expect.
Alternatively, gcc supports options to disable the use of intrinsics: -fno-builtin or for granular control, -fno-builtin-function. There are further options that may be useful if you're doing something like building a homebrew kernel or some other kind of on-the-metal app.
In a non-toy example another file may include the one you missed. Reviewing the output from the pre-processor is a nice way to see what you end up with compiling.