0

I try to write a multi-thread program, and meet some problems.

After I run main.c, and I get

i: 0
new thread 0
new thread 1
i: 1
i: 1

//main.c
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
void* routine(void* arg)
{
    int id = (intptr_t) arg;
    printf("new thread %d\n", id);
    pthread_exit((void*)(intptr_t) id);
}
int main()
{
    pthread_t t[2];
    int i;
    for(i=0; i<2; i++)
    {
        int ret = pthread_create (&t[i], NULL, &routine,  (void *)(intptr_t) i);
        if(ret != 0) {
            printf("Error: pthread_create() failed\n");
            return -1;
        }
    }
    int id;
    /////////here
    for(i=0; i<2; i++)
    {
        printf("i: %d\n",i);
        pthread_join(t[i], (void **)&id);
    }
    /////////here
    pthread_exit(NULL);
}

My problems are

  • Why the last loop runs thrice?
  • If I change pthread_t t[2] to pthread_t t and create twice, is it possible to call pthread_join twice?

Thanks for your time reading my question.

alk
  • 69,737
  • 10
  • 105
  • 255
Shawn Huang
  • 187
  • 2
  • 14

1 Answers1

2

First add some more debug-logging:

int id;
for(i=0; i<2; i++)
{
    printf("i: %d\n",i);
    pthread_join(t[i], (void **)&id);
    printf("id[%d]: %d\n", i, id);
}

Re-run and memorize the output.

Then change it to look like this

int id;
for(i=0; i<2; i++)
{
    void * pv;   
    printf("i: %d\n",i);
    pthread_join(t[i], &pv); /* Add error checking here! */
    id = (intptr_t) pv;
    printf("id: %d\n", id);
}

Re-run and compare to the previous version.


As a rule of thumb:

If facing the seemingly need to cast in C (not C++), always think twice, as there are only very, very, very rare cases where casting in C is necessary and not only just hiding a programming mistake by silencing the compiler.

alk
  • 69,737
  • 10
  • 105
  • 255
  • I still think its a little bit weird when `i` change to 0 after calling `pthread_join` in my case. I did not pass `i` to that function. But anyway, thanks for your answer and suggestions. – Shawn Huang Oct 09 '16 at 16:27
  • 1
    @ShawnHuang: `pthread_join()` expects a `void**`, the address of a pointer, it will de-references it to become a `void*` and then assigns to this `void*` a pointer value, which probably is 8byte, The memory referenced by what you passed is an `int`, it's only is 4 byte wide. So some other 4 bytes get overwritten. These 4 bytes most likely belong to the `i`. – alk Oct 09 '16 at 16:34
  • I have never accounted for this side effect while casting. Thanks again for your help. – Shawn Huang Oct 09 '16 at 16:49