I am trying to pass a struct as a parameter to pthread_create and seem to be getting some strange results.
The struct has two members, first one being an int and the second one is a function pointer:
typedef struct
{
int num;
void (*func)(int);
} foo_t;
The function I am trying to use within the struct:
void myfunc(int mynum)
{
printf("mynum: %d\n", mynum);
}
This is the declaration of the struct I will be passing to my thread:
foo_t f;
f.num = 42;
f.func = &myfunc;
The call to pthread_create:
pthread_create(&mythread, NULL, mythreadfunc, &f);
And finally, my thread function:
void mythreadfunc(void *foo)
{
foo_t f = *(foo_t *)foo;
printf("num: %d\n", f.num); // Prints: num: 32776 (undefined?)
(*f.func)(f.num); // Segfaults (again, undefined?)
...
It seems that the cast within mythreadfunc doesn't seem to work and I can't figure out why. Any suggestions? Thanks.
Papergay's answer is definitely one solution, but another approach you can use if you want to avoid dynamic allocation is just using synchronization. My favorite approach is putting a semaphore with initial-value zero in the struct and having the parent wait on the semaphore and the child post the semaphore after it's done reading the values out of the structure.
You are passing your foo_t f by reference. If you are changing your f from your pthread_create-calling function or somewhere else, for example leaving the corresponding scope would remove/delete f from the stack, then your reference inside your thread is (most likely) invalid. At least you should not access it anymore.
Use pointers with dynamically allocated variables instead.
Though I can not prove that this is happening with the code you have presented.
Edit:
A pointer is used to store the address of an object/variable. In C/C++ you can have it point to a dynamically allocated memory segment. Look up malloc/new for this. You can do what is called dereferencing with pointers and access the objecct/variable itself.
You can pass the pointer per value, which means, that you won't pass the object/variable itself, but the address(= position) of the object/variable inside your RAM. The memory management of dynamically allocated varialbes/object lies in the responsibility of the programmer, so your object won't be deleted when the scope of the pointer ends, only the pointer which stores the address will be deleted.
Related
Edit:
(1) Title (- previous title: How can I assign the address of a pointer to an already-existing variable? -- resolve at bottom of message);
(2) 'In short';
(3) spelling / punctuation.
In short: I am trying create and then locate a struct on the heap (I want to save memory on the stack), and passing arguments into various functions to populate the struct. In previous projects I created a pointer to struct, allocated this on the heap using malloc, and finally passing the pointer as argument to functions - this worked perfectly. My question: can the same be done without the use of a pointer?
I am trying to store a struct in dynamic memory. I succeeded in a previous mini-project, but I used pointer-to-struct, and passed this pointer to all my functions. Now I am burning to know if I could simply omit passing the pointer and pass the variable struct itself into the function.
My current example
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct s_text t_text;
typedef struct s_text
{
int letters;
// some more stuff
} t_text;
int main(void)
{
t_text text;
t_text *tp;
tp = malloc(sizeof(t_text));
//&text = tp; <-- this here I tried, but error (value required as left operand of assignment)
return (0);
}
In the above code I allocate memory on the heap for the tp. This is the memory I'd like to use.
Now, on the stack, memory was reserved for (t_text) text. I would like to discard this and only use the heap.
t_text &text = malloc(sizeof(t_text)); <-- this may work in C++, i don't know, but in C definitely not.
In another post's discussion on NULL pointers, someone claimed in C++ that the address of a variable could point to NULL with the following code
int &x = *(int*)0;
but this definitely is not appreciated by my compiler. In fact, I tried several things with the address of a variable, but each time I try to set eg &text = (some address) this error pops up:
error: lvalue required as left operand of assignment.
(link to the post I refered to: ttps://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable/57492#57492 )
Below what I tried earlier (and works perfectly):
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
typedef struct s_text t_text;
void fn_prompt_user(t_text *tp);
void fn_calc_letters(t_text *tp);
typedef struct s_text
{
int letters;
// some more stuff
} t_text;
int main(void)
{
t_text *tp;
tp = malloc(sizeof(t_text));
fn_prompt_user(tp);
fn_calc_letters(tp);
return (0);
}
To conclude this post with my question: Is there a way I can pass a struct variable
as an argument to a function, or should I just accept passing pointer-to-struct is the one and only way to go?
Thanks!
-- answer to previous title's question (How can I assign the address of a pointer to an already-existing variable?): Not possible.
Error: error: lvalue required as left operand of assignment.
When declaring a variable, it is placed in memory. This memory location can not be changed, and so if int a = 3; a is an lvalue (location value) which can be changed (to eg. 4), but &a is unchangeable, therefor an rvalue (so is 3). So &a = ptr_a; will never work. Thanks for the clarification.
You can pass a struct to a function, like ....
int myfunc(t_text mytext) {....}
then ...
t_text thistext;
...
myfunc(thistext);
and this puts the entire struct onto the stack for the subroutine to use.
but the C language has no 'ref' feature like C++.
You can ...
tp = (t_text *)malloc(sizeof(t_text));
myfunc(*tp);
==
Your second example, passing pointers to objects, is a very conventional means of using structs in C. It has the advantage of not needlessly copying structs to the stack, merely pointers. It has the disadvantage of allowing functions to modify the objects that are pointed to. The latter problem can be remedied by declaring that the argument points to a const struct. Like:
void fn_promt_user(const t_text *tp) {...}
should I just accept passing pointer-to-struct is the one and only way to go?
Basically, yes.
C does not have "pass by reference" built into the language. If you want to have a function populate or otherwise modify a struct for you (or any other object for that matter), passing a pointer is the normal and idiomatic way of doing that. There is no real alternative, short of ugly macro hacks and stuff like that.
I'm writing a very simple code in which i need to use some threads.
When I create first type of thread i pass argument with pthread_create:
fman thread_arg;
thread_arg.sd=sda;
char* split = strtok(buffer, "|");
thread_arg.wcount=atoi(split);
split = strtok(NULL,"");
strcpy(thread_arg.id, split);
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
And everything works fine, but in function registerF I need to do something like this:
wman thread_arg;
thread_arg.sd=foremans_fd[ix];
thread_arg.fmanix=ix;
strcpy(thread_arg.id,tmpr);
pthread_create(&thread_temp, NULL, registerW, &thread_arg);
Those arguments are structures defined by me:
typedef struct fman
{
int sd;
char id[100];
int wcount;
} fman;
typedef struct wman
{
int sd;
int fmanix;
char id[100];
} wman;
And when I check it by printf("%x, args) I get the same address but values are different inside. Where is my mistake?
One likely problem is here:
fman thread_arg;
[...]
pthread_create(&thread_temp, NULL, registerF, &thread_arg);
Note that the thread_arg object is located on the stack, and thus will be destroyed (and likely overwritten by other stack variables) when the function it is declared in returns.
pthread_create(), on the other hand, launches a thread that will run asynchronously with this function, which means that the thread can (and often will) run after the function you excerpted has returned, which means that by the time the thread dereferences &thread_arg, thread_arg has likely already been destroyed and that pointer is now pointing to some other data that was written into the same stack location later on.
Unless you are doing something special to make sure that the struct's lifetime is long enough to include all of the spawned thread's accesses to the struct, then the fact that this code ever works is pure luck (i.e. the scheduler just happened to schedule the thread to run and perform all of its accesses to the struct before the struct was destroyed/overwritten). You definitely can't depend on that.
In order to fix the problem, you need to either allocate the struct on the heap (so that it won't be destroyed when the function returns -- the spawned thread can then free the struct when it is done using it), or use some kind of synchronization mechanism (e.g. a condition variable) to cause the main thread to block inside your function until the spawned thread has indicated that it is done accessing the struct.
The thread struct in the running thread is treated like a block of memory and accessed using offsets. Since your fman and wman structs have different orders (4+100+4) vs (4+4+100), it's likely that you're getting right struct but reading from different memory location, given the passed struct to this thread is fman, and it's being accessed as wman.
Try changing them both to same signature, as in, int, int, char* and it should work.
Suppose I have the following C code:
#include <stdio.h>
#include <stdlib.h>
#define NUM_PEOPLE 24
typedef struct {
char **name;
int age;
} person_t;
void get_person_info(person_t *person);
int main(int argc, char **argv) {
for (int i = 0; i < NUM_PEOPLE; i++) {
person_t new_person;
get_person_info(&new_person);
}
return 0;
}
where get_person_info() just fills out the person_t struct to which a pointer is passed in. Is it necessary to malloc() memory for new_person within main()? That is, should the line
person_t new_person;
instead be
person_t *new_person = (person_t *) malloc(sizeof(person_t));
and then change get_person_info() to accept a person_t ** instead of a person_t *?
Sorry if this question is confusing -- I'm not sure whether or not this is a case where it is necessary to reserve memory, given that a pointer to that memory is passed into get_person_info() to avoid causing a segmentation fault.
Both are correct, it depends on where you want to use the person_info.
Allocating on the stack :
for (int i = 0; i < NUM_PEOPLE; i++) {
person_t new_person;
get_person_info(&new_person);
}
Creates a person_t object on the stack and fills the new_person object with data, because the loop only does that, the object goes out of scope on the next loop iteration and the data is lost.
Using malloc :
for (int i = 0; i < NUM_PEOPLE; i++) {
person_t *new_person = malloc(sizeof(person_t));
get_person_info(new_person);
}
Creates a person_t object on the heap and fills it with data, because its allocated on the heap the new_person object will outlive the loop scope which currently means that you're leaking memory because you have no pointer pointing at the data of the person_t object of the previous loop cycle.
Both ways are correct !!
person_t *new_person = (person_t *) malloc(sizeof(person_t));
and then change get_person_info() to accept a person_t ** instead of a person_t *?
you don't need to change parameter of function -void get_person_infperson_t *person);.Just pass pointer to it in main like this -
get_person_info(new_person);
But in previous way without allocating memory , you won't be able to use it outside the block it is defined in whereas if your program depend on its life you can allocate memory to it on heap.
In your code you posted new_person is used inside loop only so if you don't intend to use to outside loop you probably won't need dynamic allocation .
But if you want to use it outside loop also you should use dynamic allocation. But don't forget to free it.
Not sure whether or not to malloc memory for a struct?
The short answer is: no need to do it in your case. If you want to use your object outside the forloop you could do it by dynamically allocated memory, namely:
person_t *new_person = malloc(sizeof(person_t));
and then call it with:
get_person_info(new_person);
In you example, the object is used within the loop, thus there is no need to do it.
Note:
when you use dynamically allocated memory you should always free it, at the end to avoid memory leaks.
Edit:
As pointed out by #Johann Gerell, after removing the redundancy of the casting of the return type of malloc, in C, the allocation would look like:
person_t *new_person = malloc(sizeof(person_t));
malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. The use of casting is required in C++ due to the strong type system, whereas this is not the case in C.
Your confusion stems from not understanding object storage duration and pointers well. Let's see each one separately to get some clarity.
Storage Duration
An object can have automatic or dynamic storage duration.
Automatic
Automatic, as the name says, would be managed by the compiler for you. You just define a variable, use it and when it goes out of scope the object is destroyed automatically for you. A simple example:
if (flag) {
int i = 0;
/* some calc. involving i */
}
// i is dead here; it cannot be accessed and its storage is reclaimed
When the control enters the if's scope, memory large enough to hold an int will be allocated automatically and assigned the value 0. Once your use of i is over, when the control exits the scope, the name i goes out of scope and thus will no longer be accessible by the program and also its storage area allocated automatically for you would be reclaimed.
Dynamic
Lets say you want to have objects dynamically allocated i.e. you want to manage the storage and thereby the lifetime of the object without the scope or the compiler coming in your way, then you'd go on by requesting storage space from the platform using malloc
malloc(sizeof(int));
Notice that we're not assigning the return value of malloc to any pointer as you're used to seeing. We'll get to pointers in a bit, lets finish dynamic objects now. Here, space large enough to hold an int is handed over to you by malloc. It's up to you to free it when you're done with it. Thus the lifetime of this unnamed int object is in your hands and would live beyond the scope of the code that created it. It would end only when you explicitly call free. Without a matching free call getting called, you'd have the infamous memory leak.
Pointers
A pointer is just what its name says - an object that can refer to another object. A pointer is never what it is pointing at (pointee). A pointer is an object and its pointee is another separate, independent object. You may make a pointer point to another named object, unnamed object, or nothing (NULL).
int i = 0;
int *ptr1 = &i; // ptr1 points to the automatic int object i
int *ptr2 = malloc(sizeof(int)); // ptr2 points to some unnamed int object
int *ptr3 = NULL; // ptr3 points to nothing
Thus the reason most people confuse pointers for dynamically allocated pointees comes from this: the pointee, here, doesn't have a name and hence they're referred to always via their pointers; some people mistake one for the other.
Function Interface
The function taking a pointer is appropriate here, since from the caller's viewpoint it's a flexible function: it can take both automatic and dynamic objects. I can create an automatic variable and pass it in, or I can pass a dynamic variable too:
void get_person_info(person_t *person);
person_t o { };
get_person_info(&a);
person_t *p = malloc(sizeof(person_t));
get_person_info(p);
free(p);
Is it necessary to malloc() memory for new_person within main()?
No. You can define an automatic variable and pass it to the function. In fact it's recommended that you try to minimize your usage of dynamic objects and prefer automatic objects since
It minimizes the chances of memory leaks in your code. Even seasoned programmers miss calling the matching free to a malloc thereby introducing a memory leak.
Dynamic object allocation/deallocation is far slower than automatic variable allocation/deallocation.
A lot of dynamic allocation deallocation causes memory fragmentation.
However, automatic variables are generally allocated in the stack and thus the upper limit on the number and size on how much you can create on the stack is relatively lower than what you can allocate dynamically (generally from the heap).
change get_person_info() to accept a person_t ** instead of a person_t *?
No, if you did so, the option of passing automatic variables would still be possible but cumbersome:
void foo(int **o);
int i = 0;
int *p = &i; // p is redundant
foo(&p);
int *p = malloc(sizeof(int));
foo(&p);
As opposed the simpler
void bar(int *o);
int i = 0;
bar(&i);
int *p = malloc(sizeof(int));
bar(p);
Suppose we have
struct me {
int b;
};
void main() {
struct me *m1;
m1->b=3;
}
My quesrion is that , as m1 is a pointer of type me and is currently
not holding any address of variable of type me then how we can access b which is member of me
through a pointer which is not pointing to any variable of type me and if we can then which variable of type me is accesing a?
It's either
struct me m1;
m1.b = 3;
or
struct me *m1 = malloc(sizeof(struct me));
m1->b = 3;
When you deal with pointers in C, you usually need to do 3 things:
create the pointer
make sure the memory is allocated where the pointer should point
make the pointer point to that memory
Your solution only did the first of these.
The reason why your printf works, is that the actual assignment and reading still works. You were overwriting some random memory in your process, this time without any disastrous result. But it's pure "luck". You could have ended up with a segmentation fault as well.
1) You must allocate space for the object you're pointing to first
2) Then - and only then - can you assign the value m1->b = 3
void main()
{
struct me *m1=malloc(sizeof(struct me)); //here allocating the memory first
m1->b=3;
//do what you want to do
free(m1); //once you allocate the memory, you have to free it after your job is done
}
If you do not allocate memory and access (like you have done), you are accessing a part of memory where m1 points to. It will compile fine. But if m1 has a value outside the segment of your code, it will give rise to segmentation fault. Also if it is within your segment, it may overwrite other values. So it is always desirable to allocate the memory before using it.
I'm currently self-studying C for mastering an university project. In that project we have several signatures given that we need to implement for solving our task. After several hours of trying to make some progress, I must admit that I'm totally confused about the return types of functions. I will show you some code:
This is a structure given to represent numbers in the power to the basis 32.
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int uint32;
typedef struct
{
int n;
uint32* words;
}
foo;
We need to implement some functions like the one with the following signature:
foo add(foo* a, foo* b);
As can you see, the function takes two pointers to the structure as parameters, and returns the value of a structure, and not the pointer to it. That means that I have to locally create an instance of foo and return it.
foo add(foo* a, foo* b)
{
foo result = {1, malloc(sizeof(uint32))};
// do something with result
return result;
}
1) Is there anything wrong in this attempt? In my production code I get problems with accessing the value of the returned structure: it seems to they have changed after the structure was returned. Unfortunately I was not able to reproduce that behaviour in a more simple application, which got me even more worried that I'm doing this all wrong. I have also tried to allocate memory with malloc for the variable result, but that only seems to work if I create a pointer to foo, which seems to be no option, because I can't return the pointer.
2)
I'm looking for a way to cast (probably not the correct term) the return type back into a pointer.
Lets just say I have this code:
foo* bar1 = malloc(sizeof(foo));
bar1->n = 1;
bar1->words = malloc(bar1->n * sizeof(uint32));
bar1->words[0] = 4294967295;
foo* bar2 = malloc(sizeof(foo));
bar2->n = 1;
bar2->words = malloc(bar2->n * sizeof(uint32));
bar2->words[0] = 21;
foo bar3 = add(bar1, bar2);
Works fine. How could I now use the value of bar3 to call the add function again. Like this:
foo bar4 = add(bar1, bar3);
After also tried various attempts with creating foo* and trying to assign values, but they all failed and I decided to post this question to get some nice answer that helps me understanding C a little bit more.
1) To access the returned structure you only need to do something like:
printf("[bar3] n %d words %d\n", bar3.n, *(bar3.words));
2) To pass bar3 again to the function add. You need to pass the mem address of bar3 which can be accessed by using the operator &:
foo bar4 = add(bar1, &bar3);
or
foo bar3_p = &bar3;
foo bar4 = add(bar1, bar3_p);
If you do it like this you can keep the definition of the function without returning a pointer.
You're looking for the address-of operator, &. &foo3 will return a pointer to foo3.
Update I withdraw my previous explanation. I ran your code through valgrind and indeed you don't produce any leaks or incorrect memory accesses. The way you have it, the struct is returned by value, so it is copied into a new struct on return. The only thing you would have to do is free() the words pointer when you're done.
Your strange results might be the result of something you're doing that's not shown here.
You need to return a pointer to foo:
foo* add (foo* a, foo* n) {
foo result* = malloc(...);
/* do some addition */
return result;
}
Don't forget to free() the foo structs which are obtained this way.
To undesrtand the reason why your way doesn't work, consider the lifetime of variables declared within the add() scope:
add() is entered.
A new foo struct is created and assigned to the variable result.
The function add() returns and the memory for variables within that scope is freed.
Outside of add(), the caller receives a struct stored at a location in memory which is marked as unused.
Attempts to access that struct produce undefined results because the memory where it is located could be allocated for other data.
Consider the flow of the solution I presented:
add() is entered.
New memory is allocated on the heap and the address of that memory is stored in result.
The function add() returns the value of result (an integer indicating an address in memory).
Outside of add(), the location pointed at by result is still an allocated location on the heap, and the pointer returned may be safely dereferenced.
When you are done with the struct at that location, you call free(result) and that location is marked as unused.
Hope that helps! For further information, you should investigate what the memory heap is and how allocation works.