In my company's code we have general get() and set() methods for interop between certain components. However, if I try to run PREfast I get inundated with warnings because PREfast doesn't realize that the get() method initializes the given parameters.
The problem is that since those methods are very general, they don't simply take a parameter (which I could mark with _Out_ or similar, but an array of structs which holds the data as to which data should be returned.
In code (greatly simplified):
typedef struct
{
int type;
int* data;
} ARGS;
void get(int count, ARGS* args)
{
for (int i = 0; i < count; i++)
*(args[i].data) = 42; // Actually handled by internal methods
}
// Sample Usage
void foo()
{
int value;
ARGS args[1];
args[0].type = 1234;
args[0].data = &value;
get(1, args);
// Do something with value
// PREfast complains that value is uninitialized (error C6001)
printf("%d", value);
}
Is there any way to annotate this so PREfast knows that args.data is initialized by get()? Or is this too complex for PREfast to handle?
EDIT: If I use get(1, &args), then the warning goes away. So there is some heuristic in PREfast which can handle this case, but I haven't found out if it is possible to trigger it externally:
void get2(int count, ARGS(* args)[1]) // Needs the size of args, or it won't compile below
{
for (int i = 0; i < count; i++)
*(*args)[i].data = 42; // Actually handled by internal methods
}
// Sample Usage
void foo2()
{
int value;
ARGS args[1];
args[0].type = 1234;
args[0].data = &value;
get2(1, &args);
// Do something with value
printf("%d", value);
}
This should fix the warning.
void foo()
{
int value=0;
...
}
Note that get() will be called in runtime only. Since, PREfast is a static analysis tool, it might report that the value is uninitialized. Nevertheless, initializing a variable before use is always a best practice in C.
Another way would be to use the PREfast suppress as below:
void foo()
{
int value;
ARGS args[1];
args[0].type = 1234;
args[0].data = &value;
get(1, args);
// Do something with value
// PREfast complains that value is uninitialized (error C6001)
#pragma prefast(suppress:C6001 , "PREfast noise: the variable value will be initialized by get method in a line above")
printf("%d", value);
}
It suppresses the warnings in the next line after the suppress statement.
Also, do add the following code in you header files(or source files) just before using the pragma prefast in your code:
#ifndef _PREFAST_
#pragma warning(disable:4068)
#endif
to avoid 4068 warning to be flagged. NOTE: pragma prefast is an extension to the PREfast AST compiler only and may not be supported by other compilers.
Related
I have a function like:
typedef struct
{
bool x;
bool y;
bool z;
} myStruct;
static void myFunction(const myStruct *pTomystruct_out)
{
if (pTomystruct_out->x == TRUE)
{
/*Do Something*/
}
}
Now for some debug purpose I want to add debug code to set the pointer parameter always to TRUE.
Within the function before the if statement I want to do something like:
pTomystruct_out.x = TRUE /*This is not the correct way*/
How to do this in the right way?
Thanks!
pTomystruct_out is a pointer, so you have to dereference that for manipulating what is pointed.
You can use * opetator to dereference:
(*pTomystruct_out).x = TRUE;
Also you can use -> operator where A->B means (*A).B:
pTomystruct_out->x = TRUE;
Also, this is not enough because the pointer pTomystruct_out is marked as const.
You can use a cast to non-const pointer for having it allow modifications.
((myStruct*)pTomystruct_out)->x = TRUE;
This is syntactically collect, but it may be dangerous to modify the object that is thought not to be modified. Creating a copy of the object and modifying the copy is safer.
typedef struct
{
bool x;
bool y;
bool z;
} myStruct;
#if 1 /* debug mode */
static void myFunction(const myStruct *pTomystruct_out_arg) /* change argument name */
{
myStruct pTomystruct_debug_temp = *pTomystruct_out_arg; /* make a copy */
myStruct *pTomystruct_out = &pTomystruct_debug_temp; /* declare a variable with original argument name */
pTomystruct_out->x = TRUE; /* modify the copy */
#else
static void myFunction(const myStruct *pTomystruct_out)
{
#endif
if (pTomystruct_out->x == TRUE)
{
/*Do Something*/
}
}
As mentioned in previous answer, the parameter is const, disabling modifications to that parameter. You probably don't want it to be const.
To add debug code, you can make use of macros. You can have a header file contain macros, like seen below:
#define DEBUG
Or:
#define DEBUG 1
Included a header with this macro allows you to write your function as follows:
static void myFunction(const myStruct *pTomystruct_out)
{
#ifdef DEBUG
pTomystruct_out.x = TRUE
#endif
}
If you used the latter macro, #define DEBUG 1 (which I recommend), you can use an if-statement instead:
static void myFunction(const myStruct *pTomystruct_out)
{
#if DEBUG
pTomystruct_out.x = TRUE
#endif
}
I recommend using #define DEBUG 1, because then you don't have to comment out the macro whenever you don't want it. You can just set it to 0.
If you don't want a header file, you can use the -D flag using gcc, like gcc <INPUTFILE> -DDEBUG.
I would like to create a wrapper for c functions, so that I can convert a function call of the form ret = function(arg1,arg2,arg3); into the form /*void*/ function_wrapper(/*void*/);. That is similar to function objects in C++ and boost bind.
Is this possible? how can I do it?
Update:
To explain in more details what I am looking for:
We start with this function:
int f(int i){
//do stuff
return somevalue;
}
Obvioulsy, it is called like this:
// do stuff
int x = 0;
ret = f(0);
// do more stuff.
I would like to do some magic that will wrap the function into void function(void)
struct function_object fo;
fo.function_pointer = &f;
fo.add_arg(x, int);
fo.set_ret_pointer(&ret);
fo.call();
Note: I saw that there was a vote for closing this question and marking it as unclear. Please do not do that. I have a legitimate need to get this question answered. If you need explanation, ask and I will be glad to elaborate.
I came up with a better code that might allow you to do what you want. First I'll explain how it works, show the code and explain why I still don't think it's a good idea to use it (though the code might open doors for improvements that addresses those issues).
Functionality:
Before you start using the "function objects", you have to call an initialization function (FUNCTIONOBJ_initialize();), which will initialize the mutexes on every data structure used in the library.
After initializing, every time you want to call one of those "function objects", without using the parameters, you will have to set it up first. This is done by creating a FUNCTIONOBJ_handler_t pointer and calling get_function_handler(). This will search for a free FUNCTIONOBJ_handler data structure that can be used at the moment.
If none is found (all FUNCTIONOBJ_handler data structures are busy, being used by some function call) NULL is returned.
If get_function_handler() does find a FUNCTIONOBJ_handler data structure it will try to lock the FUNCTIONOBJ_id_holder data structure, that holds the ID of the FUNCTIONOBJ_handler of the function about to be called.
If FUNCTIONOBJ_id_holder is locked already, get_function_handler() will hang until it's unlocked by the thread using it.
Once FUNCTIONOBJ_id_holder is locked, the ID of the grabbed FUNCTIONOBJ_handler is wrote on it and the FUNCTIONOBJ_handler pointer is returned by get_function_handler.
With the pointer in hand, the user can set the pointer to the arguments and the return variable with set_args_pointer and set_return_pointer, which both take a void * as arguments.
Finally, you can call the function you want. It has to:
1 - Grab the FUNCTIONOBJ_handler ID from the FUNCTIONOBJ_id_holder data structure and use it to get a pointer to the FUNCTIONOBJ_handler itself.
2 - Use the FUNCTIONOBJ_handler to access the arguments.
3 - Return by using one of the return function (on the example we have ret_int, which will return an integer and unlock the FUNCTIONOBJ_handler)
Below is a simplified mind map describing a bit of what is going on:
Finally, the code:
funcobj.h:
#include <stdio.h>
#include <pthread.h>
#define MAX_SIMULTANEOUS_CALLS 1024
typedef struct {
//Current ID about to be called
int current_id;
//Mutex
pthread_mutex_t id_holder_mutex;
} FUNCTIONOBJ_id_holder_t;
typedef struct {
//Attributes
void *arguments;
void *return_pointer;
//Mutex
pthread_mutex_t handler_mutex;
} FUNCTIONOBJ_handler_t;
FUNCTIONOBJ_handler_t FUNCTIONOBJ_handler[MAX_SIMULTANEOUS_CALLS];
FUNCTIONOBJ_id_holder_t FUNCTIONOBJ_id_holder;
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value);
void FUNCTIONOBJ_initialize(void);
FUNCTIONOBJ_handler_t *get_function_handler(void);
funcobj.c:
#include "funcobj.h"
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->return_pointer = pointer;
}
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->arguments = pointer;
}
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value){
if(this->return_pointer){
*((int *) (this->return_pointer)) = return_value;
}
pthread_mutex_unlock(&(this->handler_mutex));
}
void FUNCTIONOBJ_initialize(void){
for(int i = 0; i < MAX_SIMULTANEOUS_CALLS; ++i){
pthread_mutex_init(&FUNCTIONOBJ_handler[i].handler_mutex, NULL);
}
pthread_mutex_init(&FUNCTIONOBJ_id_holder.id_holder_mutex, NULL);
}
FUNCTIONOBJ_handler_t *get_function_handler(void){
int i = 0;
while((0 != pthread_mutex_trylock(&FUNCTIONOBJ_handler[i].handler_mutex)) && (i < MAX_SIMULTANEOUS_CALLS)){
++i;
}
if(i >= MAX_SIMULTANEOUS_CALLS){
return NULL;
}
//Sets the ID holder to hold this ID until the function is called
pthread_mutex_lock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
FUNCTIONOBJ_id_holder.current_id = i;
return &FUNCTIONOBJ_handler[i];
}
main.c:
#include "funcobj.h"
#include <string.h>
//Function:
void print(void){
//First the function must grab the handler that contains all its attributes:
//The FUNCTIONOBJ_id_holder is mutex locked, so we can just access its value and
//then free the lock:
FUNCTIONOBJ_handler_t *this = &FUNCTIONOBJ_handler[FUNCTIONOBJ_id_holder.current_id];
//We dont need the id_holder anymore, free it!
pthread_mutex_unlock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
//Do whatever the function has to do
printf("%s\n", (char *) this->arguments);
//Return the value to the pointed variable using the function that returns an int
ret_int(this, 0);
}
void *thread_entry_point(void *data){
int id = (int) data;
char string[100];
snprintf(string, 100, "Thread %u", id);
int return_val;
FUNCTIONOBJ_handler_t *this;
for(int i = 0; i < 200; ++i){
do {
this = get_function_handler();
} while(NULL == this);
set_args_pointer(this, string);
set_return_pointer(this, &return_val);
print();
}
return NULL;
}
int main(int argc, char **argv){
//Initialize global data strucutres (set up mutexes)
FUNCTIONOBJ_initialize();
//testing with 20 threads
pthread_t thread_id[20];
for(int i = 0; i < 20; ++i){
pthread_create(&thread_id[i], NULL, &thread_entry_point, (void *) i);
}
for(int i = 0; i < 20; ++i){
pthread_join(thread_id[i], NULL);
}
return 0;
}
To compile: gcc -o program main.c funcobj.c -lpthread
Reasons to avoid it:
By using this, you are limiting the number of "function objects" that can be running simultaneously. That's because we need to use global data structures to hold the information required by the functions (arguments and return pointer).
You will be seriously slowing down the program when using multiple threads if those use "function objects" frequently: Even though many functions can run at the same time, only a single function object can be set up at a time. So at least for that fraction of time it takes for the program to set up the function and actually call it, all other threads trying to run a function will be hanging waiting the the data structure to be unlocked.
You still have to write some non-intuitive code at the beginning and end of each function you want to work without arguments (grabbing the FUNCTIONOBJ_handler structure, unlocking the FUNCTIONOBJ_id_holder structure, accessing arguments through the pointer you grabbed and returning values with non-built-in functions). This increases the chances of bugs drastically if care is not taken, specially some nasty ones:
Increases the chances of deadlocks. If you forget to unlock one of the data structures in any point of your code, you might end up with a program that works fine at some moments, but randomly freeze completely at others (because all function calls without arguments will be hanging waiting for the lock to be freed). That is a risk that happens on multithreaded programs anyways, but by using this you are increasing the amount of code that requires locks unnecessarily (for style purposes).
Complicates the use of recursive functions: Every time you call the function object you'll have to go through the set up phrase (even when inside another function object). Also, if you call the recursive function enough times to fill all FUNCTIONOBJ_handler structures the program will deadlock.
Amongst other reasons I might not notice at the moment :p
I have a structure containing pointers to callback functions like such:
typedef void (*LOAD_CB)(resource* r);
typedef void (*UNLOAD_CB)(resource* r);
typedef void (*CREATE_CB)(void* i);
typedef void (*DESTROY_CB)(void* i);
typedef struct /*_resman_callbacks*/ //<-- causes error
{
LOAD_CB load;
UNLOAD_CB unload;
CREATE_CB create;
DESTROY_CB destroy;
} resman_callbacks;
I then initialize these functions at runtime and add them to a list containing other callbacks with a call to a function:
register_extension(".my_file_extension", &(/*error appears here*/resman_callbacks){load, unload, create, destroy});
This does not cause an error when my structure does not have a name (such as _resman_callbacks), however when a name is provided in the structure definition, my IDE shows an error "a compound literal of type "resman_callbacks" is not allowed". This does not cause any runtime issues, nor does it cause the code to fail compilation. Which leaves me with two questions
A) Is this something to be concerned about, considering that my code still functions?
B) Why is the structure having a name causing the error to appear?
My IDE is Visual Studio Express 2013.
Edit:
Added the declaration and implementation of register_extension, plus other relevant data.
//resman.h
void register_extension(char* file_ext, resman_callbacks* cb);
//resmain.c
typedef struct
{
char* ext; //extension associated with this resource
resman_callbacks* cb; //structure containing callback functions
} registered_extension;
typedef struct
{
registered_extension* reg_ext; //list of registered extensions
unsigned short ext_ct; //current number of registered extensions
unsigned short size; //maximum number of registered extensions
} ext_manager;
static ext_manager extman;
void register_extension(char* ext, resman_callbacks* callbacks)
{
if (extman.ext_ct == extman.size)
{
extman.size = extman.size * 2;
extman.reg_ext = realloc(extman.reg_ext, extman.size);
}
*(extman.reg_ext + extman.ext_ct) = (registered_extension) { ext, callbacks };
extman.ext_ct = extman.ext_ct + 1;
}
Assuming that you have the following functions declared before you actually use them in your code:
void load(resource* r);
void unload(resource* r);
void create(void* i);
void destroy(void* i);
Try this:
resman_callbacks cb = {load, unload, create, destroy};
register_extension(".my_file_extension", &cb);
I download a code example written in C, but don't understand one instruction. And besides, w
hen i try to compile the code the compiler throws me an error just in the line that i don't understand.
Code:
// Global vars
static int getting_text = 0;
static char *the_text; // Definition Part
static void (*text_entered)(); // Definition Part 2
// method
int add_text(unsigned char key)
{
char msg[] = "x";
int len;
if(!getting_text) return 0;
if(key==8) /* backspace */
{
len = strlen(the_text);
the_text[len-1] = '\0';
}
else if(key==13 || key==9) // cr or tab ends
{
getting_text = 0;
text_entered(the_text); // Execution Part
}
else
{
msg[0] = key;
strcat(the_text, msg);
}
glutPostRedisplay();
return 1;
}
The compiler throws me an error about there are too many arguments in the method's calling. But i don't if it's a method the static void (*xxx)() or if other thing.
Thanks in advance.
EDIT: The following only applies to C++. Did you use g++ or some other C++ compiler instead of a C compiler?
text_entered is a function pointer to a function that doesn't take any arguments, hence the error, because you're passing it a character pointer. I assume it should change to,
static void (*text_entered)(char*);
This is of course assuming text_enterered actually gets set to a function that takes a char* argument and it isn't just being called wrong.
/*language C code*/
#include "windows.h"
typedef struct object_s
{
SRWLOCK lock;
int data;
} object_t, *object_p; /*own and pointer type*/
void thread(object_p x)
{
AcquireSRWLockExclusive(&x->lock);
//...do something that could probably change x->data value to 0
if(x->data==0)
free(x);
else
ReleaseSRWLockExclusive(&x->lock);
}
void main()
{
int i;
object_p object=(object_p)malloc(sizeof(object_t));
InitializeSRWLock(&object->lock);
for(i=0;i<3;i++)
CreateThread(0,0,thread,object,0);
}
As you can figure out in the codes above, what I have to accomplish is to let one thread conditionally free the object on which the other two may block. Codes above are obviously flawed because if object is set free along with the lock, all blocking threads give us nowhere but wrong.
A solution below
/*language C code*/
#include "windows.h"
typedef struct object_s
{
/*change: move lock to stack in main()*/
int data;
} object_t, *object_p; /*own and pointer type*/
void thread(void * x)
{
struct {
PSRWLOCK l;
object_p o;
} * _x=x;
AcquireSRWLockExclusive(_x->l);
//...do something that could probably change x->data value to 0
if(_x->o->data==0)
free(_x->o);
ReleaseSRWLockExclusive(&x->lock);
}
void main()
{
int i;
SRWLOCK lock; /*lock over here*/
object_p object=(object_p)malloc(sizeof(object_t));
InitializeSRWLock(&lock);
/*pack for thread context*/
struct
{
PSRWLOCK l;
object_p o;
} context={&lock, object};
for(i=0;i<3;i++)
CreateThread(0,0,thread,&context,0);
}
works in this case but not applicable however, in my final project because there is actually a dynamic linked list of objects. By applying this solution it means that there must be a list of locks accordingly, each lock for an object and moreover, when a certain object is set free, its lock must be set free at the same time. There is nothing new compared with the first code section.
Now I wonder if there is an alternative solution to this. Thank you very much!
The solution is to not allocate the lock together with the data. I would suggest that you move the data out of that struct and replace it with a pointer to the data. Your linked list can then free the data first, and then the node, without any problems. Here's some pseudo code:
typedef struct
{
lock_t lock;
int* data_ptr;
} something_t;
void init_something (something_t* thing, ...)
{
thing->lock = init_lock();
thing->data_ptr = malloc(...); // whatever the data is supposed to be
}
void free_something (somthing_t* thing)
{
lock(thing->lock);
free(thing->data_ptr);
thing->data_ptr = NULL;
unlock(thing->lock);
}
...
void linked_list_delete_node (...)
{
free_something(node_to_delete->thing);
free(node_to_delete);
}
...
void thread (void* x)
{
lock(x->lock);
//...do something that could probably change x->data_ptr->data... to 0
if(x->data_ptr->data == 0)
{
free_something(x->data_ptr->data);
}
unlock(x->lock);
}
AcquireSRWLockExclusive(lock);
if(_x->o->data==0)
free(_x);
ReleaseSRWLockExclusive(lock);
As a sidenote, a C program for Windows can never return void. A hosted C program must always return int. Your program will not compile on a C compiler.
Also, CreateThread() expects a function pointer to a function returning a 32-bit value and taking a void pointer as parameter. You pass a different kind of function pointer, function pointer casts aren't allowed in C, nor am I sure what sort of madness Windows will execute if it gets a different function pointer than what it expects. You invoke undefined behavior. This can cause your program to crash or behave in unexpected or random ways.
You need to change your thread function to DWORD WINAPI thread (LPVOID param);