3

The first argument of pthread_create is a pthread_t pointer. In the hello program below, if the first argument is a pointer to pthread_t (pthread_t*) instead of a pthread_t (pthread_t) the program ends with Segmentation fault...why?

I don't remember seeing pthread_t* as the declared type of the first argument of pthread_create.
And chapter 2 of Butenhof's book Programming with POSIX Threads says:

To create a thread, you must declare a variable of type pthread_t [not pthread_t*].

But according to the specification the first argument of pthread_create is a pointer to pthread_t, so why the segmentation fault?



Segmentation fault
pthread_t* thr;
pthread_create(thr, NULL, &hello, NULL);



Runs OK
pthread_t thr;
pthread_t* pntr = &thr;
pthread_create(pntr, NULL, &hello, NULL);



hello program:
#include <pthread.h>
#include <stdio.h>

void * 
hello(void *arg){
  printf("Hello\n");
  pthread_exit(NULL);
}

int 
main(int argc, char **argv){
  pthread_t thr = 1;
  pthread_create(&thr, NULL, &hello, NULL);



  pthread_join(thr, NULL);

  return 0;
}

pthread_create prototype:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);
user454322
  • 7,300
  • 5
  • 41
  • 52
  • See the difference between _defined_ and _declared_ in http://stackoverflow.com/questions/1433204/what-are-extern-variables-in-c – user454322 May 22 '13 at 08:43

3 Answers3

9
pthread_t* thr;
pthread_create(thr, NULL, &hello, NULL);

declares a pointer to a pthread_t without allocating storage for it. When you call pthread_create, it'll try writing to *thr. This is at an undefined location and will almost certainly fail.

pthread_t thr;
pthread_t* pntr = &thr;
pthread_create(pntr, NULL, &hello, NULL);

works because you've declare storage (thr on the stack) for a pthread_t.

Note that the second, working, version can be simplified to what is used in your hello program

pthread_t thr;
pthread_create(&thr, NULL, &hello, NULL);

...which declares a pthread_t on the stack then passes a pointer to it into pthread_create.

simonc
  • 41,632
  • 12
  • 85
  • 103
4

It is because if you simply declare a pointer, you can't expect it to point to allocated, initialised memory.

When you instead declare a pthread_t it gets allocated its own little block of memory that you can then get the address to with the & operator and pass it to pthread_create.

user454322
  • 7,300
  • 5
  • 41
  • 52
  • Right. Without `&` the pointer is not initialized. Thank you. – user454322 Dec 19 '12 at 16:20
  • The `&` operator takes the address of the `pthread_t` as a pointer of type `pthread_t *` and this can then be used to call `pthread_create`. It doesn't initialise the pointer so much as simply create a valid pointer to an allocated area of memory. –  Dec 19 '12 at 16:30
  • Perhaps I wasn't clear. With initializing the pointer, I meant taking the address of (point to, i.e., assigning the address of `thr` to `pntr`) the memory where the pthread_t refers. Note that: just between `pthread_t* pntr = &thr;` and the call to `pthread_create` `pntr` is pointing to UNallocated memory (because thr has not been initialized). – user454322 Dec 19 '12 at 16:47
  • `pntr` is pointing to *allocated* memory because it points to `&thr`; `thr` could very well be *uninitialised*, though. –  Dec 19 '12 at 17:18
  • I see your point. Then `pntr` points to `&thr` which in turn points to unallocated memory... rigth? – user454322 Dec 19 '12 at 17:43
  • `&thr` is the address of (pointer to the data of) `thr`, which is allocated memory on the stack (automatically allocated for you) created by the variable declaration `pthread_t thr;`. However, because you are merely declaring `thr`, it is not *initialised* which means that both `pntr` and `thr` are *allocated* but only `pntr` is initialised: It contains the value `&thr`. In the example that works, nothing is pointing to unallocated memory, which is exactly why it works. –  Dec 19 '12 at 17:48
  • Thanks for the followup. With `thr`, _which is allocated memory on the stack (automatically allocated for you) created by the variable declaration_ `pthread_t thr` do you mean that the solely `pthread_t thr` allocates memory? Before `pthread_create` what `thr` is pointing to? – user454322 Dec 20 '12 at 01:33
0

If you want to create some thread you can use below code:

pthread_t* thread_handles;
thread_handles = malloc(thread_count * sizeof(pthread_t));
for (thread = 0; thread < thread_count; thread++)
{
  pthread_create(&thread_handles[thread], NULL, threadFunc, (void*)input);
}

In this way you should allocate memory for your handles before calling pthread_create, just like when you want to create some "struct" you should first allocate memory for them.

m.w.
  • 471
  • 4
  • 9
Mehdi
  • 1
  • 2