C Function Pointer void value issue - c

I've been working on an assignment for an operating systems class (so please, only tips, no full answers), and one function whose parameters and return types were provided by my instructor but who's content was filled by me is throwing an error. The function is as follows:
void start_thread(void (*function)(void))
{
TCB_t* stackPointer = malloc(8192); //8192 is a provided value for assignment
TCB_t tcb;
tcb = init_TCB(&tcb, function, stack, sizeof(stack));
AddQueue(RunQ, tcb);
}
The following function is from the line the error is thrown on, this function was defined for the assignment and should not be changed.
void init_TCB (TCB_t *tcb, void *function, void *stackP, int stack_size)
{
memset(tcb, '\0', sizeof(TCB_t));
getcontext(&tcb->context);
tcb->context.uc_stack.ss_sp = stackP;
tcb->context.uc_stack.ss_size = stack_size;
makecontext(&tcb->context, function, 0);
}
I am unfamiliar with C and especially the idea of function pointers, but all of my research says this code should not be throwing errors, but it is continually throwing the following:
error: void value not ignored as it ought to be

tcb = init_TCB(&tcb, function, stack, sizeof(stack));
needs to be
init_TCB(&tcb, function, stackPointer, 8192);
I'll let you figure out why those changes make sense.
If they don't make sense, add a comment.

Related

Declare a pointer to structure in const expression

I am new to C and can't yet freely navigate trough my program memory. Anyways, I am creating a static memory data type (gc_menu) that should hold a pointer to created at execution time structure (mcl_items).
For simplicity mcl_items structure have one virtual method (push) that is going to be run inside of gc_menu_add_item and also assigned to the gc_menu static space. push saves an menu item name (letter) and method to mcl_item virtual object.
mcl_items.h code:
[...]
typedef struct Items_t {
int8_t size;
char names[64];
void (*methods[64])();
// Interface
void (*push)(struct Items_t *self, char c, void (*method)());
}mcl_items;
mcl_items *new_mcl_items();
void mcl_items_push(mcl_items *self, char c, void (*method)());
mcl_items.c code:
[...]
#include "mcl_items.h"
mcl_items *new_mcl_items() {
fprintf(stderr, "MCL_Items: Generating a new set of mcl_items..");
// Build a virtual object
mcl_items *items = calloc(1, sizeof(struct Items_t));
items->push = mcl_items_push;
// Set data
items->size = 0;
return items;
}
void mcl_items_push(mcl_items *self, char c, void (*method)()) {
fprintf(stderr, "MCL_Items: pushing a new item..");
self->names[self->size] = c;
self->methods[self->size] = method;
self->size ++;
}
gc_menu.h code:
#include "items.h"
typedef struct {
// Interface
void (*add_item)(char c, void (*method)());
// Data
mcl_items *items;
}__gc_menu;
extern __gc_menu const gc_menu;
gc_menu.c code:
static void gc_menu_add_item(char c, void (*method)) {
fprintf(stderr, "GC_Menu: Passing an new item..");
fprintf(stderr, "length = %i\n", gc_menu.items->size);
gc_menu.items->push(gc_menu.items, c, method);
}
__gc_menu const gc_menu = {gc_menu_add_item, // Virtual methods
new_mcl_items}; // Data
After callng gc_menu.add_item the segmentation fault occurs and gc_menu.items->size is equal to 72, not 0 as is defined in the definition of new_mcl_items.
main.c code:
gc_menu.add_item('q', xw->end(xw));
GC_Menu: Passing an new item..length = 72
[1] 66021 segmentation fault (core dumped) ./3D_scean
So what am I doing wrong? Why is there such a weird data written to instances of my gc_menu.items?
You've initialized gc_menu.items to new_mcl_items, i.e. a pointer to the function new_mcl_items (which should give you a warning since it is of type mcl_items *(*)(void) and not mcl_items *).
It looks like what you want is to actually call the function new_mcl_items() and set gc_menu.items to the value that new_mcl_items() returns. You can't do this with an initializer; initializers of global or static objects must be known at compile or link time. Standard C doesn't have "constructors".
So you'll have to remove the const from the declaration and definition of gc_menu, and add code to main (or some function called by main, etc) to initialize gc_menu.items at run time.
gc_menu.h:
extern __gc_menu gc_menu;
gc_menu.c:
__gc_menu gc_menu = {
gc_menu_add_item,
NULL // or whatever else you like
};
main.c or whatever you have called it:
int main(void) {
// ...
gc_menu.items = new_mcl_items();
// ...
}

Passing function pointer to arg of pthread_create function

I have a function void startScanner(...) taking two function pointer as arguments: userType *vConfig(void) and void * vCallback(void). In this function i would like to create a thread and call vCallback() function in the function thread created. So i decided to pass vCallback as args to pthreadcreate.
The code of startScanner function :
void startScanner(tUsrStatus (*vConfig)(), void* (vCallback)()){
if(pthread_create(&scannerThread, NULL, scannerThreadFunc, vCallback))
{
printf("Thread creation fails!\n");
}
}
The scannerTread function:
static void *scannerThreadFunc(void *arg()){
void *funcptr(void) = arg;
while(1)
{
funcptr();
}
pthread_exit(NULL);
}
I get the following error:
error: function ‘funcptr’ is initialized like a variable
error: nested function ‘funcptr’ declared but never defined
How can i fix this?
Syntax errors aside (*) , it's impossible in standard C to pass a function pointer in a void *. There's a fundamental difference between pointers to functions and pointers to data, they can't be converted into each other. This is because there might be platforms where function and data pointers would differ even in size, or refer to different address spaces, or whatever.
But of course, there's a simple way to achieve what you want: Put your function pointer inside a struct and pass a pointer to that.
typedef (*callback)(void);
typedef struct threadargs
{
callback cb;
} threadargs;
void mycallback(void)
{
// ...
}
void *threadfunc(void *arg)
{
threadargs *ta = arg;
// call your callback:
ta->cb();
return ta; // or: return 0, or some pthread_exit(), ...
}
int main(void)
{
pthread_t thread;
threadargs ta = { mycallback };
pthread_create(&thread, 0, threadfunc, &ta);
// make sure "ta" lives for as long as the thread executes,
// here just wait until it exits:
pthread_join(&thread, 0);
}
add error checking etc.
(*) as for the concrete error you're getting, a function pointer needs parantheses around the identifier, so instead of
void *funcptr(void) = arg;
you'd have to write
void (*funcptr)(void) = arg;
To facilitate the usage of function pointers, it's common to typedef them, as seen in my example above. Anyways, as explained above, this wouldn't solve your problem here.

how to call function pointer in a struct?

I am working with the xinu embedded operating system in c. I created a new header file and declared a struct:
struct callout {
uint32 time; /* Time of delay in ms */
void *funcaddr; /* Function pointer */
void *argp; /* Function arguments */
uint32 cid; /* Callout id for the specific callout */
char *sample;
};
In my main, I try to declare a struct object and function the funcaddr to a function.
void test();
process main(void) {
struct callout *coptr;
coptr->sample ="hellowolrd";
coptr->funcaddr = &test;
(coptr->funcaddr)(coptr->argp); //error here
kprintf("coptr %s \n", coptr->sample);
return OK;
}
void test() {
kprintf("this is the test function \n");
}
I try to invoke the function pointer through the struct but I am getting an error:
main.c:30:19: error: called object is not a function or function pointer
(coptr->funcaddr)();
Please show what is the correct syntax to invoke the function pointer.
You have declared funcaddr as an object pointer. To declare a function pointer it looks like this:
struct callout {
uint32 time;
void (*funcaddr)(); // <-------- function pointer
Then the rest of your code should work.
If you didn't see an error message for the line coptr->funcaddr = &test; then I would recommend adjusting your compiler settings, it's important to have the information available that the compiler can tell you.

Modified struct in some functions changes pointer and causes free() to fail

Pardon me for running multiple statements on one line, but this is what I don't understand. I have three functions named function1, function2 and function3 and each call makeblock, makeblock2, and makeblock3 respectively. See code below. I was trying to get them all to produce the same result on the screen. makeblock function works properly and the result after calling function1 is:
1 A
2 B
function2 and function3 do not work properly and produce a segmentation fault when attempting to free the memory pointer. I suspect it has to do with how the pointer is handled in makeblock2 and makeblock3 functions respectively.
So basically, I'm looking for a shortcut to making the data accessible without returning a modified address value back to the caller. Something shorter than block* dat=*datain;block** data=&dat; would be ideal provided it works yet my attempts in makeblock2 and makeblock3 have failed.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct{int a;char b;} block;
void printdata(block* data){
while(data->a != 0){printf("%d %c\n",data->a,data->b);data++;}
}
void makeblock3(block** datain){
block** data=&(*datain);
(**data).a=1;(**data).b='A';(*data)++;
(**data).a=2;(**data).b='B';(*data)++;
}
void makeblock2(block** datain){
block** data=datain;
(**data).a=1;(**data).b='A';(*data)++;
(**data).a=2;(**data).b='B';(*data)++;
}
void makeblock(block** datain){
block* dat=*datain;block** data=&dat;
(**data).a=1;(**data).b='A';(*data)++;
(**data).a=2;(**data).b='B';(*data)++;
}
void function1(){block* data=calloc(1,100000);makeblock(&data);printdata(data);free(data);}
void function3(){block* data=calloc(1,100000);makeblock3(&data);printdata(data);free(data);}
void function2(){block* data=calloc(1,100000);makeblock2(&data);printdata(data);free(data);}
int main(){function3();return 0;}
Simple solution: don't pass by reference
void makeblock(block* data){
data->a=1; data->b='A'; data++;
data->a=2; data->b='B'; data++;
}
If you really want to pass by reference but don't want the referred object to change (which is contrary to the usual reason to pass by reference), then make a copy of the referred-to object:
void makeblock(block** data_p){
block* data = *data_p;
data->a=1; data->b='A'; data++;
data->a=2; data->b='B'; data++;
}

Bad memory access while calling function

Actually i developing using unit test.
But i break down my code in other form to ask for the error that i faced.
I have these declaration in my header file
typedef struct
{
void *topOfStack;
}Stack;
typedef enum {NUMBER,OPERATOR,IDENTIFIER}Token;
int operatorEvaluate(Stack *numberStack , Stack *operatorStack);
void * pop(Stack *stack);
The following is the respective source file
#include "try.h"
void *pop(Stack *numberStack)
{
Token *newToken = NUMBER;
return newToken;
}
int operatorEvaluate(Stack *numberStack , Stack *operatorStack)
{
Token *first = (Token*)pop (numberStack);
if(numberStack != operatorStack)
{
if(*first == NUMBER)
return 1;
}
return 0;
}
This is the source file that i call the functions which is main
#include "try.h"
#include <stdio.h>
int main ()
{
Stack numberStack;
Stack operatorStack;
int num;
num = operatorEvaluate(&numberStack , &operatorStack);
printf("This is the returned value: %d",num);
return 0;
}
When i tried to compile, the unit test tell me that bad memory access.
So i try to use eclipse to compile these, and windows tells that the .exe had stop working.
Hope someone can help me, i stuck for a long time...
Enable compiler warnings.
In particular, this makes zero sense:
Token *newToken = NUMBER;
That's a pointer, and you're assigning a value.
I cannot propose a fix, as I have no idea what you're doing.
That pop() function isn't touching the stack, and is returning an enum converted to a pointer. If you try to access anything through that pointer, it's going to provoke undefined behavior.
Your pop function is wrong in a few ways. You probably want it to actually pop your stack, rather than return a constant (which it isn't doing either, by the way!)...something like this:
void *pop(Stack *numberStack)
{
return numberStack->topOfStack;
}
but if you do that it'll still crash, because you never initialize your stack OR fill the topOfStack pointer.

Resources