简体   繁体   中英

segmentation fault when using threads - c

This is the first time that i am using threads and I started with a simple program. The program takes n arguments and creates n-2 threads. The thing is I get a segmentation fault and I don't know why.

Here's the code:

#include <stdio.h>  
#include <string.h> 
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

void *
removeBytes (int i, char* argv[])
{
  printf ("%d, %s\n", i, argv[i]);
  return NULL;
}  


int main (int argc, char *argv[])
{

  pthread_t threads[argc - 3];
  int err;
  int i;  
  int *ptr[argc - 3];

  printf ("argc = %d\n", argc);

  for (i = 0; i < argc -3; i++)
    {
      err =
        pthread_create (&(threads[i]), NULL,
                        removeBytes(i+1,&argv[i+1]), NULL);
      if (err != 0)
        {
          printf ("\nCan't create thread: [%d]", i);
        }
      else
        { 
          printf ("\nThread created successfully\n");
        }
    }

  for (i = 0; i < argc - 3; i++)
    {
      pthread_join (threads[i], (void **) &(ptr[i]));
      printf("pthread_join - thread %d",i);
    }

  return 0;
}

Example: my program is called mythread so when I run it ./mythread f1 f2 f3 f4 f5 f6 the output is:

argc = 6

1,f2
Thread created successfully

2,f4
Thread created successfully
3, (null)

And why does it take f2 as argv[1] and f4 as argv[2] ?

UPDATE:

 typedef struct{
    int i;
    char* argv;
  }Data;

  void* removeBytes(void* arg){
    Data* data = (Data*)arg;   
    printf("%d, %s\n",data->i, data->argv);
    free(data);
    return NULL;
  }



  int main(int argc, char** argv){
    Data* data;

    pthread_t threads[argc-3];

    int i;
    int err;
    for(i=0; i < argc-3;i++){
      data = (Data*)malloc(sizeof(Data));
      data->i=i+1;
      data->argv=argv[i+1];
      err = pthread_create(&(threads[i]),NULL,removeBytes,data);
      if(err != 0){
        printf("\nCan't create thread %d",i);
      }
      else{
        printf("Thread created successfully\n");
      }
    }  

    return 0;
  }

for ./mythread f1 f2 f3 f4 f5 f6 f7 f8 the output is:

5 x "Thread created successfully". It doesn't print i or argvi[i].

You're not using pthread_create correctly :

pthread_create (&(threads[i]), NULL,
                        removeBytes(i+1,&argv[i+1]), NULL);

Here you're just calling removeBytes() and passing the result ( NULL ) as an argument of pthread_create() .

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

The third argument should be a pointer to a void* myThread(void*) function. If you want to pass arguments to your thread, you should use the void* parameter and pass it as the third argument of pthread_create .

You could take a look at this in order to learn how to use the pthread library.

Also, you probably want to to something like this :

typedef struct {
    int i;
    char* argv;
} Data;

void * removeBytes (void* arg)
{
  Data* data = (Data*) arg;
  printf ("%d, %s\n", data->i, data->argv);
  free(data);
  return NULL;
}

And then create the thread like this:

Data* data = (Data*)malloc(sizeof(Data));
data->i = i;
data->argv = argv[i+1];
err = pthread_create (&(threads[i]), NULL, removeBytes, data);

With

pthread_create (&(threads[i]), NULL,
                    removeBytes(i+1,&argv[i+1]), NULL);

You are calling removeBytes() instead of passing it as parameter.

Also, You can pass only one argument to thread function. So you need to put multiple arguments in a structure. Something like:

struct thread_args {
    int i;
    char *argv;
}

#your main code
struct thread_args *thargs;

for (i = 0; i < argc -3; i++)
{
  thargs = malloc(sizeof(*thargs));
  thargs->i = i+1;
  thargs->argv = argv[i+1];
  err =
    pthread_create (&(threads[i]), NULL,
                    removeBytes, thargs);
  if (err != 0)
    {
      printf ("\nCan't create thread: [%d]", i);
    }
  else
    { 
      printf ("\nThread created successfully\n");
    }
}
#make sure to free up thargs as well.

And update thread function as

void *removeBytes (void *arg)
{
  int i;
  char *argv;
  struct thread_args *thargs =  (struct thread_args *) arg;
  i = thargs->i;
  argv = thargs->argv;
  printf ("%d, %s\n", i, argv);
  return NULL;
} 

There is problem in

pthread_create (&(threads[i]), NULL,
                    removeBytes(i+1,&argv[i+1]), NULL);

Syntax of pthread_create is

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                      void *(*start_routine) (void *), void *arg);

It takes start routine as a callback. In your case, you are calling removeBytes in main thread that is before spawning and returning NULL. So, callback is NULL.

So, modify your removeBytes accordingly as per your need and call

pthread_create (&(threads[i]), NULL, removeBytes, argv[i+1]);

It takes f2 as argv[1] and f4 as argv[2] simply because when you pass &argv[i+1] you actually pass pointer to the (i+1)-th element of the array and you also pass i+1 as index.

So if you have argv equals [mythread, f1, f2, f3, f4, f5, f6] at first you'll get [f1, f2, f3, f4, f5, f6] in removeBytes. And when you're accessing i+1 = 1 element you'll get f2. Next time you'll get [f2, f3, f4, f5, f6] and i+1 = 2 so you'll get f4

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM