How to invoke invalid handler function like gets_s() does? - c

I used the following code to invoke an invalid parameter handler if the user enters more than 4 characters.Actually it's the gets_s() function which invokes the handler.
...
char arr[5];
_invalid_parameter_handler newHandler;
newHandler = myInvalidParameterHandler;
_set_invalid_parameter_handler(newHandler);
gets_s(arr,4);
...
}
void myInvalidParameterHandler(const wchar_t* expression,const wchar_t* function,
const wchar_t* file,
unsigned int line,
uintptr_t pReserved)
{
...
}
Now, my question is how gets_s() calls/invokes the handler internally?I am asking this because I want to do something similar in my program.For eg. lets say I have a function declared like-
EDIT:
If when running the above code the user enters more than 4 characters then the handler is invoked.If I comment out the invalid handler related code then my program will crash.The same I want to achieve.
If some one uses my function he should get same behavior as I get when using gets_s.Please don't suggest this is good or bad.I just want to learn it.gets_s doesn't know which handler func I am gonna set.Similarly my function doesn't know which invalid handler func the user will set.I think there might be some C runtime global variable of type _invalid_parameter_handler which the '_set_invalid_parameter_handler()' func sets which gets_s uses.

In my opinion 1 and 3 are the same, and yes you could do it like that. Have all your functions call a function pointer in some global struct and you're set.
Set up a global object that contains a function pointer and some bookkeeping dat
When a function detects something wrong it can call the handler
But don't do it. It's way better to return an error status than to automatically call a function when something "feels" wrong. Then you can check the return status and act on it, instead of some automatic handler taking over.
EDIT
From your comment I believe you don't know about function pointers.
/* here is the handling function */
void handler(char *msg)
{
fprintf(stderr, "%s\n", msg);
}
void (*err_handler)
void some_function_like_gets(void *arg)
{
if (NULL == arg) {
(*err_handler)("Oh noes! You passed a NULL pointer :(");
return;
}
}
int main()
{
/* ... */
/* setting up handler */
err_handler = handler;
/* calling function */
some_function_like_gets(NULL);
/* ... */
}
EDIT 2
The sad part is that you downvoted this even though the MSDN page says:
[in] pNew The function pointer
to the new invalid parameter handler.

Related

How to let the user bind a click handler function to a button?

I am currently building my own GUI using the SDL2 library for a program i wrote in C (c89).
Problem
I want to let the user of my code pass its own click handler function, which would be called every time a click event is fired on the surface of the corresponding button.
What I tried
I thought i could use function pointers like this :
bind_ClickHandler(void (*function)(void)) {/* bind it to a button */}
but, obviously, it is too limiting for the user.
So i tried to use stdarg.h :
/* ... : arguments to pass to the click handler */
bind_ClickHandler(void (*function)(), int nb_args, ...)
{
void *arg_pt;
va_list args;
va_start(args, nb_args);
/* I don't know what to do so i cast it as a garbage pointer */
arg_pt = va_arg(args, void *);
/* repeat this in a loop to save the args and bind the click handler to a button */
}
With this code i can pass arguments to the click handler, but only if i know their types.
What I want
I want to use something like the second piece of code i showed you to save the args to pass to the click handler, but it doesn't work because i need to know the types of the args to use va_arg().
Just pass a single void* pointer. Like qsort_r or pthread_create[*]. The user only needs one pointer - and that pointer will point anywhere the user wants to.
void (*clickhandler_user_function)(void *) = NULL;
void *clickhandler_user_function_arg = NULL;
void bind_ClickHandler(void (*function)(void*arg), void *function_arg) {
// store function and fucntion_arg somewhere
clickhandler_user_function = function;
clickhandler_user_function_arg = function_arg;
}
A single pointer is just enough:
struct user_context_s {
int some_number;
const char *some string;
// etc.
};
void user_function_that_operates_on_user_context(void *p) {
struct user_context_s *ctx = p;
printf("My number is: %d\n", ctx->some_number);
}
int main() {
// user can use malloc() and manage the lifetime of it's context
struct user_context_s ctx = {1, "blabla"};
bind_ClickHandler(user_function_that_operates_on_user_context, &user_context);
}
[*] - or thrd_create or fopencookie uses void *cookie or the standard sigevent uses void *sival_ptr; in sigval to pass context when sigev_notify == SIGEV_THREAD.

Call any functions from one place using va_list as arguments

I have main update where I do access control before call. I would like to use one place in my code where call any urgent funcs.
I have a struct ACTION:
{
FUNC_PROTOTYPE pfnAction;
unsigned int argsnum;
va_list argsval;
};
When I need invoke func, I do:
1 Put func and arguments to queue; 2 Pop them on the next update
{
ACTION action;
while(!Queue_isEmpty())
{ // check and pop urgent functions
if(Queue_Pop(&action))
{
action.pfnAction(action.argsnum, action.args);
va_end(action.args);
}
}
}
For example, I try to call
void func(unsigned int argsnum, va_list args)
But my args inside func is corrupted.
I thought, that problem while I'm pop from queue:
Queue_Pop(P_ACTION p_res)
{
if(!Queue_isEmpty())
{
p_res->pfnAction = header->pfnAction;
p_res->argsnum = header->argsnum;
if(0 < p_res->argsnum)
{
p_res->argsval = header->argsval;
va_end(header->argsval);
}
...
}
}
But action.args is fine.
As #mSalters says, you can't pass va_list around - it is only valid while in the stack frame of the function with variable args.
On an architecture which strictly passes on the stack, you might be able to hack it by storing the initial address pointed to by va_list, and the address after walking through all expected arguments, then copying all the memory between the two addresses into an allocated buffer. This would have to be done before you queued it. On the queue pop side, you would fake out va_arg, by making va_list to point to your copy.
I wouldn't recommend actually doing this for any purposes other than experimentation.
And on many modern architectures, this won't work, as some variables are also passed in registers. See this article for details on how messy va_args can be.
You can't pass a vararg list around as an object, not even with va_list. That just doesn't work / is Undefined Behavior.
If you're programming in C++, then (1) don't tag your questions with C and (2) store a std::function with bound arguments.

How to handle invalid passed arguments in Ansi C [closed]

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 7 years ago.
Improve this question
I am new to C and come from a back ground of newer languages (like Java and C++) and I'm not sure how to handle runtime errors like an incorrect arguments sent to a function.
for example say I want to write a function to manipulate a string (assuming any valid int is an acceptable return value):
int foo (char s[]) {
if ( strlen(s) < 1)
// ERROR
....
....
return someInt;
}
How do I handle this scenario in Ansi C if I want the function to stop immediately? In C++ or Java I would throw an exception to be caught by the caller.
You can always use the return value :
if( /* some bad parameters */ )
return -1;
And then :
int value = foo( something );
if( value == -1 )
// error
else
// no error
Or pass an another parameters :
int foo( char s[], int* value )
{
if( /* error */ )
return 1;// error code 1
// ...
*value = something;
return 0;
}
Then when you call the function you can verify if it was executed correctly :
if( foo( "something", &result ) )
{
//ok
}
else
{
// not ok
}
Both of these method implies that the caller will verify manually if there was an error
if I want the function to stop immediately
Two things.
If you want only the function to stop execution and return to caller, use a return statement. Also, you may want to use some predefined or user-defined error codes as the failure case return value to distinguish the reason of failure from the caller.
If you want the program itself to terminate, call exit().
The standard way to do error handling in any C program is to reserve the return value of the function for an error code.
Most typically this is a custom enum type. Example:
typedef enum
{
FOO_OK,
FOO_ERR_STRLENGTH,
FOO_ERR_DIVIDE_BY_ZERO,
...
} foo_err_t;
foo_err_t foo_func (/* parameters */)
{
if (strlen(s) < 1)
{
return FOO_ERR_STRLENGTH;
}
...
return FOO_OK;
}
Then you document the function properly and state which error codes it may return, and what is causing them.
What should be done upon error is usually no business of your routines, but something that should be decided by the caller. In particular, your routines should never decide to terminate the whole program. That decision should be taken by the outer-most caller (top of the call stack), i.e from main().
If I thinking of your question right, most type errors will be caught on compilation. If you want to just return early, you can simply call return. Often times, error handling, C programers will add a goto for the error:
struct Data *
create_data ()
{
struct Data *data = malloc(sizeof(struct Data));
if (data == NULL)
goto exit;
/* do stuff with data */
exit:
return data;
}
That will return NULL if there was no memory. But you might want to exit early for another reason. So, if you need to exit the program gracefully (and free all the things you have taken), you're going to need a central exit point.
I usually have a function like
void bail (const char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
vfprintf(stderr, fmt, argp);
va_end(argp);
exit(EXIT_FAILURE);
}
It prints to STDERR and returns a non-0 exit as well. You could easily modify this to accept any data you need to free.
Your major options are:
Have the return value combine both the error status and the actual value. For example if your function only intends to return non-negative values, then you could say that negative return values indicate an error.
Return an error code (0 for success) and give the function's output via a reference parameter.
Return the function's output and give the error code via a reference parameter.
Other options include using a global (or thread-local) variable for error status (not a good idea IMHO), or returning a struct that contains both the return information and the error status.

Pass a c++ lambda to old c function pointer

I have to create a c++ wrapper to a old c library.
In a class method I must call a c function that takes with other stuff also a function pointer(it is a event handler and the function takes a function that is fired when a event happens).
A simple example of it is this:
void myclass::add_handler(std::function<void()> handler, otherstuff...)
{
/*
* Many things.
*/
type_of_function_pointer_accepted_by_old_c_library_add_handler nameofvariable =
[handler](same_arguments_as_in_definition_of_the_old_c_function_pointer_accepted)
{
/*
* Many other things with other stuff to be done before the
* handler but always only when fired and not when myclass::add_handler is called.
*/
handler();
};
old_c_library_add_handler(nameofvariable);
/*
* Last things.
*/
}
The compiler complains, as I know, that I can't assign a lambda with capture to an old c function pointer.
The question is: how can I do to solve?
Here is an example. We are using the fact that lambdas that do not capture anything are, according to the C++ standard, usable as function pointers.
/* The definition of the C function */
typedef void (*PointerToFunction)();
void old_c_function(PointerToFunction handler, void* context);
/* An example of a C++ function that calls the above C function */
void Foo(std::function<void()> handler)
{
auto lambda = [] (void* context) {
auto handler = reinterpret_cast<std::function<void()>*>(context);
(*handler)();
};
old_c_function(&lambda, &handler);
}
I believe you can use the same idea in your context.

Function pointers and callbacks in C

I have started to review callbacks. I found this link on SO:
What is a "callback" in C and how are they implemented? It has a good example of callback which is very similar to what we use at work. However, I have tried to get it to work, but I have many errors.
#include <stdio.h>
/* Is the actual function pointer? */
typedef void (*event_cb_t)(const struct event *evt, void *user_data);
struct event_cb
{
event_cb_t cb;
void *data;
};
int event_cb_register(event_ct_t cb, void *user_data);
static void my_event_cb(const struct event *evt, void *data)
{
/* do some stuff */
}
int main(void)
{
event_cb_register(my_event_cb, &my_custom_data);
struct event_cb *callback;
callback->cb(event, callback->data);
return 0;
}
I know that callbacks use function pointers to store an address of a function. But there are a few things that I find I don't understand:
What is meant by "registering the callback" and "event dispatcher"?
This code compiles and runs under GCC with -Wall.
#include <stdio.h>
struct event_cb;
typedef void (*event_cb_t)(const struct event_cb *evt, void *user_data);
struct event_cb
{
event_cb_t cb;
void *data;
};
static struct event_cb saved = { 0, 0 };
void event_cb_register(event_cb_t cb, void *user_data)
{
saved.cb = cb;
saved.data = user_data;
}
static void my_event_cb(const struct event_cb *evt, void *data)
{
printf("in %s\n", __func__);
printf("data1: %s\n", (const char *)data);
printf("data2: %s\n", (const char *)evt->data);
}
int main(void)
{
char my_custom_data[40] = "Hello!";
event_cb_register(my_event_cb, my_custom_data);
saved.cb(&saved, saved.data);
return 0;
}
You probably need to review whether the call back function gets the whole struct event_cb or not - usually, you'd just pass the data because, as demonstrated, otherwise you have two sources of the same information (and a spare copy of the pointer to the function that you're in). There is a lot of cleanup that can be done on this - but it does work.
A question in the comments asks: Is this a good example of a callback?
Succinctly, no - but in part because there isn't sufficient infrastructure here.
In a sense, you can think of the comparison function passed to the qsort() or bsearch() functions as a callback. It is a pointer to a function that is passed into the generic function that does what the generic function cannot do for itself.
Another example of a callback is a signal handler function. You tell the system to call your function when the event - a signal - occurs. You set up the mechanisms ahead of time so that when the system needs to call a function, it knows which function to call.
The example code is attempting to provide a more elaborate mechanism - a callback with a context. In C++, this would perhaps be a functor.
Some of the code I work with has very fussy requirements about memory management - when used in a particular context. So, for testing, I use malloc() et al, but in production, I have to set the memory allocators to the specialized allocators. Then I provide a function call in the package so that the fussy code can override the default memory allocators with its own surrogate versions - and provided the surrogates work OK, the code will behave as before. Those are a form of callback - again, a form that does not need much (or anything) in the way of user context data.
Windowing systems have event handlers (callbacks) that are registered and that the GUI main event loop will call when events occur. Those usually need user context as well as the event-specific information provided by the GUI system.
What is meant by "registering the callback" and "event dispatcher"?
"registering the callback" is the act of telling the underlying system which precise function to call, and (optionally) with which parameters, and possibly also for which particular class of events that callback should be invoked.
The "event dispatcher" receives events from the O/S (or GUI, etc), and actually invokes the callbacks, by looking in the list of registered callbacks to see which are interested in that event.
Without the compiler output it's hard, but I can see a few problems;
int event_cb_register(event_ct_t cb, void *user_data);
Should be
int event_cb_register(event_cb_t cb, void *user_data);
The my_custom_data variable does not exist when it's used here;
event_cb_register(my_event_cb, &my_custom_data);
This pointer is never initialized;
struct event_cb *callback;
And in;
callback->cb(event, callback->data);
You cannot pass the name of a type ('event') to a function, you must pass an instance of that type.
int event_cb_register(event_ct_t cb, void *user_data);
What is that type event_ct_t? Do you mean event_cb_t?
struct event_cb *callback;
Creates an uninitialized pointer to a structure event_cb. Note mostly this points to garbage.
callback->cb(event, callback->data);
You are trying to call garbage. You need initialization:
struct event_cb callback;
callback.cb = my_event_cb;
callback.data = 42;
or some such stuff.
Registering a callback means that you are specifying which function should be called when the event of interest occurs. Basically you are setting the function pointer when registering a callback.
You created a pointer of the struct you declared, but it does not point to anything:
struct event_cb *callback;
You should just create a type of your struct:
struct event_cb callback;
and then pass its address to the functions.

Resources