In the code below, what is the role of the int sid=*(int*)args construct?
void *thread_p(void *args)
{
int sid=*(int*)args,i,size=0;***This initialisation in the thread function means what?***
char msg[100];
while(1)
{
for(i=0;i<100;i++)
msg[i]='\0';
recv(sid,msg,100,0);
printf("\nClient:%s",msg);
printf("\nServer:");
gets(msg);
size=strlen(msg);
send(sid,msg,size,0);
if((strcmp(msg,"exit"))==0)
{
close(sid);
exit(1);
}
}
}
I'm going to make an assumption here that thread_p is a pthread_create start routine. Such a start routine is required to accept a void pointer, which in C and C++ means a pointer to an untyped block of memory. Now, in addition to a start routine, pthread_create also accepts a void pointer argument, which it passes to the start routine. It is up to the caller of pthread_create to coordinate the call to pthread_create with the code in the start routine. So if the start routine given to pthread_create assumes the void pointer points to, say, an integer, then the call to pthread_create must pass a pointer to an integer as the arg parameter to keep things in sync. This is a type-unsafe interface. The compiler won't help you make sure these are in sync, and if they are not, you'll get undefined behavior.
Your thread_p function is assuming that the arg passed to it actually points to an integer. It is first casting the void pointer to an integer pointer (that is the (int*)args part) and then dereferencing the pointer to get the integer that it points to (that's the * in front of the (int*)args). If the caller of pthread_create passed it thread_p, but failed to pass the address of an int as the arg parameter, the code would have undefined behavior.
Related
I have code like this:
typedef struct _Statistics {
Some code here
} Statistics;
void function1(char *string, Statistics *statistic){
Some code here
function1(string1, statistic);
}
int main(){
Statistics statistic;
function1(string, &statistic);
}
This is probably idiotic question, but I don't understand pointers completely:
I understand why I use & in main function, & send address of variable statistic, so that in function1 I can modify it. But why don't I use & in recursive function1?
Because &statistic (in function1()) is the memory address of the pointer, not the address contained by the pointer.
The type of &statistic is Statistics** in function1().
Few words about pointers
Let's say we define the following variables:
char c = 'a';
char *p_c = &c;
Now, we will print the values and memory addresses of p_c and c:
printf("%c\n", c); // will print 'a'
printf("%c\n", *p_c); // will print 'a'
printf("%p\n", &c); // will print the memory address of c
printf("%p\n", p_c); // will print the memory address of c
printf("%p\n", &p_c); // will print the memory address of p_c
Finally we define a char**, a pointer to a pointer to char:
char **p_pc = &p_c;
printf("%c\n", **p_pc); // will print 'a'
printf("%p\n", *p_c); // will print the memory address of c
printf("%p\n", p_c); // will print the memory address of p_c
Sometimes it helps to write it this way:
void function1(char* string, Statistics* statistic){
The variable statistic is a pointer to Statistics, not the Statistics itself. If you did this in function1:
function1(string1, &statistic);
You would be passing a pointer to (because of the &) a pointer to (because of the * in the declaration) Statistics, which would be incorrect.
Your declaration of statistic in main as Statistic adds to the confusion: you're using the same variable name with different types in the two scopes.
With different variable names it's clearer:
typedef struct _Statistics {
Some code here
} Statistics;
void function1(char* string, Statistics* ptrstat){
Some code here
function1(string1, ptrstat);
}
int main(){
Statistics statistic;
function1(string, &statistic);
}
In general (i.e. most languages), you can pass by value or pass by reference. It will depend on the definition of the function and its 'signature'; i.e. the way it and its arguments are declared.
Pass-by-value is like an assignment and, if copying a larger structure, it will take longer. Also, the function only receives a copy, so you can make changes to the argument in the function, but that will only effect the function's local copy (the argument) and will make NO change to the original value (in the caller) that was passed to you.
By contrast, pass-by-reference simply passes a pointer (the address in memory) of the original value. This is much faster, (4 or 8 bytes), but it does means that the function can not only read but also write the caller's value. Sometimes you want this! Sometimes you don't.
In your main, you have the value of statistics. The function you are calling expects the address (*), so instead of passing the value, (statistic), you need to pass its address, (&statistic).
In the function, calling itself, you have a pointer to statistic (Statistics *) and you must pass a pointer to statistic (Statistics *): hence, just pass it, the pointer 'statistic'.
I do not quite understand the difference between passing to a function *mode1 or **mode2.
I wrote some examples. (note: type can be any type)
[Code 1]
#include <stdio.h>
void function (type *vet)
{
/* other */
}
int main ()
{
type *vet;
function (vet)
/* other */
return 0;
}
[Code 2]
#include <stdio.h>
void function (type **vet)
{
/* other */
}
int main ()
{
type *vet;
function (&vet)
/* other */
return 0;
}
I know: in the first case is a pointer, in the second case is a pointer to a pointer. But why for example in the second case if I pass &vet can I allocate memory in function() and free it in main() and in the first one not?
I search someone who explain me the differences well. What can I do in the two cases? How and where to malloc or realloc? And free? And modify vet in the function?
Original questions
The main (most significant) difference is whether the value in the calling function can be changed.
In the first example, the called function gets a copy of the pointer in the calling code, and cannot modify the pointer in the calling code.
In the second example, the called function gets a pointer to the pointer, and by assigning to *vet in the called function, you can modify the value in the called function.
Why in the second case if I pass &vet can I allocate memory in function() and free it in main() and in the first one not?
In the second case, the code in function() can modify the actual pointer in main(), so the value of vet in main() ends up with the allocated pointer value, which can therefore be freed. In the first case, the value in main() is not modified by the called function, so the data can't be freed by main().
How and where to malloc or realloc? And free?
In the first case, you can use malloc() or realloc() in the function, but you should also free the allocated memory before return unless your code stores the value in a global variable (in which case you can delegate to some other code to handle the free(), but it had better be very clear which code has the responsibility, and in any case using global variables is probably not a good idea). Or unless you change the function signature and return a pointer to the allocated data which should be freed by the calling code.
In the second case, you can allocate or reallocate memory in the called function and leave it allocated to be used by other functions and to be freed by the calling function.
And modify vet in the function?
In both functions, you can modify the local vet variable as you see fit; this is true of any parameter to any function. What you can't necessarily do is modify values in the calling function; you have to have a pointer to value in the calling function to do that. In the first function, you can't change the value of vet in main(); in the second, you can. In both functions, you can change what vet points at. (One minor problem is the conflation of the name vet in the three contexts — the main() and the two different functions. The name vet in the two functions points at different types of things.)
Extension questions
But is it freed in function() like, for example, this?
#include <stdio.h>
#define NUM (10)
struct example
{
/* ... */
}
void dealloc (struct example *pointer)
{
free (pointer);
}
int main()
{
struct example *e;
e = malloc (NUM * sizeof(struct example));
if (e == NULL)
return -1;
struct example *e_copy = e;
dealloc (e_copy);
return 0;
}
This code is legitimate. You pass (a copy of) the value of the pointer to the dealloc() function; it passes that pointer to free() which releases the allocated memory. After dealloc() returns, the pointer values in e and e_copy are the same as before, but they no longer point to allocated memory and any use of the value leads to undefined behaviour. A new value could be assigned to them; the old value cannot be dereferenced reliably.
And what is the difference from this?
#include <stdio.h>
#define NUM (10)
struct example
{
/* ... */
}
int main()
{
struct example *e;
e = malloc (NUM * sizeof(struct example));
if (e == NULL)
return -1;
struct example *e_copy = e;
free (e_copy);
return 0;
}
The difference between this example and the last is that you call free() directly in main(), rather than from a function dealloc().
What would make a difference is:
void dealloc(struct example **eptr)
{
free(*eptr);
*eptr = 0;
}
int main()
{
...
dealloc(&e_copy);
return 0;
}
In this case, after dealloc() returns, e_copy is a null pointer. You could pass it to free() again because freeing the null pointer is a no-op. Freeing a non-null pointer twice is undefined behaviour — it generally leads to problems and should be avoided at all costs. Note that even now, e contains the pointer that was originally returned by malloc(); but any use of that pointer value leads to undefined behaviour again (but setting e = 0; or e = NULL; or e = e_copy; is fine, and using e = malloc(sizeof(struct example)); or such like also works.
As you said, the argument in the first case is a pointer, and a copy of the pointer vet is passed. We can modify the value that vet pointed to (e.g., *vet = new value). But we cannot modify the value of the pointer vet because it is just a copy of the original vet pointer. Therefore, after first function, value of *vet may be changed, but value of vet will not.
So how could we modify the value of the pointer vet? We use the pointer to pointer. In the second function, we can allocate memory for *vet, and this modified value will be kept after the second function. So we can free it in main.
We cannot do this in first case because if we try to allocate memory in function, we just allocate memory for the copy of the pointer vet, not the original vet.
You are correct in your understanding that type *var; is a pointer to data of type and type **var; is a pointer to a pointer to data of type.
The difference you asked about, allocating memory in the function and keeping track of it, is because of the ability to assign the value to the pointer.
In C, any time you want to modify a value in a function, you must provide it a pointer the data it is to modify.
If you want to allocate memory, you must know where it is in order to use it, and later free it. If you pass only a pointer to a function, and allocate memory to it, it cannot change the value of the pointer it is passed (rather, when your program returns to the function that called this allocation function, the stack will have unloaded the address you needed); it can only read from it (which in this use is rather pointless).
Consider this, the pointer variable
type *vet;
is created on the stack of function
main()
when "function_1()" is called from main, a stack for this new function is created. Any argument passed to this function is saved on the stack of this function. In this case, the argument is a pointer variable. Now function_1() can very well change the value of this pointer variable but as soon as the function returns the stack of this function is released and any changes are lost.
But when you are passing a pointer to pointer, what you pass is actually an address of a pointer variable and not a pointer variable. So when you work on this pointer variable inside the called function, you are actually working on the memory of the stack of the calling function. And since this memory is on the stack of the calling function, any changes made by the calling function will persist even after the stack of the called function is released.
First thing is, there is no garbage collector in C. So if you don't explicitely free an allocated memory block, it will eat up memory until the process exits. That is a mighty source of memory leaks.
So, once you've allocated a memory block using malloc or similar functions, you must keep a pointer to it in order to free it someday.
If you allocate a block within a function and you plan this block to remain useable after function termination, you must pass its value to some higher level piece of code that will eventually free it, long after the function that created it has exited.
To do so, you have three basic choices:
store the pointer in some global variable
return the pointer as the function's result
have one of the function arguments specify where the pointer is to be stored
case 1
void * global_address_of_buffer;
void alloc_a_buffer (int size)
{
global_address_of_buffer = malloc (size); // block reference in global var
}
alloc_a_buffer ();
// ...
free (global_address_of_buffer);
This is clearly impractical. If you call your function twice, you will lose the address of the first buffer.
One of the innumerable illustrations of why using globals will drag you screaming right into hell.
Nevertheless, it's a possibility.
case 2
void * alloc_a_buffer (int size)
{
return malloc (size); // block reference as return value
}
void * new_buffer;
new_buffer = alloc_a_buffer (10); // retrieve pointer through return value
// ...
free (new_buffer);
This is not always possible. For instance you might want all your functions to return a status indicating success or failure, in which case the return value will not be available for your pointer.
case 3
void alloc_a_buffer (int size, void ** buffer)
{
*buffer = malloc (size); // block reference set through 2nd parameter
}
void * new_buffer;
alloc_a_buffer (10, &new_buffer); // pass pointer address to the function
// ...
free (new_buffer);
I wanted to know what's the difference between these two versions of the main() code in C:
int main() {
uint32_t a;
f(&a);
}
and
int main() {
uint32_t *a;
f(a);
}
for a function
void f(uint32_t *pointer) {
// ...
}
In your first example, you pass a pointer to uninitialized variable a. f() could store a value there, for instance, and main() would be able to use that value later.
In your second example, you pass an uninitialized pointer a. f() can't do anything useful with it.
In the first version you pass a pointer to an un-initialized variable to f().
Don't, unless f()'s task is to initialize the variable.
In the second version you pass an uninitialized pointer to function f().
Don't.
wee pointer questions!!!
Ok so you know that the function f needs to take a pointer which is exactly as it sounds an address to that actual location in memory. For the first example(f(&a)) you have to pass the address because it lives inside the stack and really isn't shared anywhere outside the life of the function. so when the function returns the memory is destroyed and no longer available. the value of the pointer is not passed just the pointer to the value is passed. which can cause problems because if you change that value then all the things that "point to it" are now changed.
Now for the second one you get the memory from the heap or where ever but that stores the address of the value not the actual value so you can manipulate it and return nothing and the value is still there.
They are defining different types of variables, without initialization.
uint32_t a; defines uint32_t variable on the stack and the function call will pass its address to the f() function.
uint32_t *a; defines a pointer on the stack and pass its value to the function. The pointer is not initialized, thus it could point to any block and any attempt to access that address will result into undefined behavior.
From the perspective of the f() function, it sees pointer values passed to it. In the first call, it can use that address, while in the second, it cannot.
In this below link
https://computing.llnl.gov/tutorials/pthreads/samples/hello.c
in the statement rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t); the coder has just passed a variable as 4th argument without passing address of that variable. Is this code correct? If yes how can we cast a variable to void *
The above link seems to be popular as it is listing first in Google for pthreads.
Well it is a bit weird, but it does what it is supposed to.
The fourth argument is sent as argument to the PrintHello function/routine. It has to be passed as a void *.
Typically you have a pointer to a dynamically allocated object that you cast to void *. But here he defines a long t, casts it to void * (address) and sends it in. Then he casts it back to a long in PrintHello, so all is fine, but a bit ugly and could have gone "horribly" wrong if he would have cast it to a pointer and tried to access the memory it pointed to.
Yes this code is correct, if you don't try to access the memory pointed to by the parameter in the thread. Just convert it to a long in the thread.
tid = (long)threadid;
It converts the pointer to a long, but it doesn't touch the memory space that the pointer points to, which is most likely junk and will cause access violations.
For example if you did:
tid = (long)*threadid;
That would cause an access violation because you are trying to access the memory at the location pointed to by threadid.
If you would rather pass the pointer to a long integer you could do something like this.
...
long* pint = (long*)malloc(sizeof(long));
*pint = t;
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)pint);
void *PrintHello(void *threadid)
{
long* tid;
tid = (long*)threadid;
printf("Hello World! It's me, thread #%ld!\n", *tid);
free(tid);
pthread_exit(NULL);
}
But that requires the use of malloc and free
Keep in mind that a pointer is nothing more than a 32 or 64bit unsigned integer which represents a location in memory, you can put any number you want in a pointer, just don't try to access the memory it points to.
Hope that helps,
-Dave
Actually the 4th argument is the parameter to be passed to the thread, for example if there is a value that needs to be passed from the main thread to the newly created one, then this is done through this 4th argument. For example:
Lets say I have a thread being created from the main loop:
Int32 l_threadid = pthread_create(&l_updatethread,NULL,Thread,&l_filter);
As you can note that I'm passing the address of a value that is going to be used in the thread being created in the following way:
void* Thread(void *p_parameter)
{
int *l_thread_filter = (int *)p_parameter;
.... then play around with this variable ...
}
I'm trying to learn on C multithreading, and I've seen a couple of rare things.
I understand that passing parameters to a thread must be done with pointers. I've found an example which I don't understand. I'll copy the relevant lines:
pthread_t tid[MAX_THREADS]
int n_veg
pthread_create(&tid[n],NULL,caracter,(void *)n_veg)
caracter is obviously a predeclared function.
Now, why do we use a void pointer casting instead of a int pointer casting? Is there any relevant difference?
Secondly, why do we use a pointer casting in the first place? Can't we use "&n_veg" like with the first parameter?
Thanks in advance.
Since both your questions are related, I'll answer them together: pthread_create takes a void * parameter, so you can really pass in any pointer you want. In this case though, we aren't actually passing a pointer, but just a simple integer value casted as a pointer. That means you will access it like this in caracter:
int value = (int)n_veg;
As you mentioned, you could very well pass an actual pointer as &n_veg and retrieve the value like this:
int value = *(int *)n_veg;
In fact, in most cases, you will need to pass more data than just an integer, such as a structure, and in that case, you must pass a pointer, as you can't simply cast it to a pointer like an integer.
One thing to keep in mind when you pass a pointer is that n_veg must not go out of scope as long as the thread is running. For example, if you do:
void test() {
int n_veg;
pthread_create(&tid[n],NULL,caracter,&n_veg);
}
then &n_veg will be invalid as soon as test returns, but the thread may still be running and will be holding an invalid address. Because of this, structures passed to threads are normally dynamically allocated, say using malloc, and the thread can free it once it has completed.
pthread_create is defined as follows:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr,
void *(*start_routine)(void *), void *restrict arg);
So it expects a void * as its last parameter. If you omit the cast, the compiler would give you a warning.