title: pthread_join leads to segmentation fault. why?
body: <p>This code receives a input file with 10 filenames, stores them into an 2d array and creates 10+1 threads: a requester and 10 converters. This is only a skeleton, so my threads only print their id, thei're not accessing any global or shared variable or something that requires a mutex. So, what should I do to avoid a segmentation fault here? </p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;pthread.h&gt;
  #include &lt;semaphore.h&gt;
  #include &lt;string.h&gt;
  #include &lt;time.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/time.h&gt;
  #include &lt;math.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;errno.h&gt;
  
  #define READ_BUFFER_LEN 16
  //#define MAX_LENGTH 128
  
  enum {
      MAX_LENGTH = 512
  };
  
  typedef struct FileNameArray {
      size_t nfiles; /* Number of file names allocated and in use */
      size_t maxfiles; /* Number of entries allocated in array */
      char **files; /* Array of file names */
  } FileNameArray;
  
  
  //GLOBAL vars
  int num_images, *threads_ids /*threads ids*/;
  pthread_t *threads;
  
  void deallocate2D(FileNameArray *names) {
      size_t i;
      for (i = 0; i &lt; names-&gt;nfiles; i++)
          free(names-&gt;files[i]);
      free(names-&gt;files);
      names-&gt;nfiles = 0;
      names-&gt;files = 0;
      names-&gt;maxfiles = 0;
  }
  
  int readInputFile(FILE *fp, FileNameArray *names) {
      num_images = names-&gt;nfiles;
      int max_lines = names-&gt;maxfiles;
      char **file_names = names-&gt;files;
      char line[MAX_LENGTH];
      char **final_filenames, **array;
  
      while (fgets(line, sizeof line, fp) != NULL) {
          if (line[0] != '\n') {
              /* Remove newline from end of file name */
              char *nl = strchr(line, '\n');
              if (nl != 0)
                  *nl = '\0';
              if (num_images &gt;= max_lines) {
                  max_lines += 100;
                  array = realloc(file_names, max_lines * sizeof (char*));
                  if (array == NULL) {
                      fprintf(stderr, "Error reallocating space for 2d array: %s\n",
                              strerror(errno));
                      return -1;
                  }
                  names-&gt;maxfiles = max_lines;
                  names-&gt;files = array;
                  file_names = array;
              }
              if ((file_names[num_images] = malloc(strlen(line) + 1)) == NULL) {
                  fprintf(stderr, "Error allocating space for 2d array: %s\n",
                          strerror(errno));
                  return -1;
              }
              names-&gt;nfiles++;
              strcpy(file_names[num_images], line);
              printf("name of file %d is: %s \n", num_images, file_names[num_images]);
              num_images++;
          }
      }
  
      printf("Num_lines: %d\n", num_images);
      //realloc to number of lines in the file, to avoid wasting memory
      if ((final_filenames = realloc(file_names, num_images * sizeof (char*))) == NULL) {
          fprintf(stderr, "Error reallocating space for 2d array: %s\n",
                  strerror(errno));
          return -1;
      }
      names-&gt;maxfiles = num_images;
      names-&gt;files = final_filenames;
      return 0;
  }
  
  void* requester(void* arg) {
  
      printf("This is the requester thread\n");
      //sleep(1);
      pthread_exit(NULL);
      return NULL;
  }
  
  void* converter(void *id) {
      int my_id = *((int*) id);
  
      printf("Thread's id is: %d\n", my_id);
      pthread_exit(NULL);
      return NULL;
  }
  
  int main(int argc, char *argv[]) {
      FileNameArray names = {0, 0, 0};
      int i, rc;
      pthread_attr_t attr;
  
  
      //check parameters
      if (argc &lt; 4) {
          fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n",
                  argv[0]);
          return -1;
      }
  
      printf("Opening input file [%s]\n", argv[1]);
      FILE *fpin = fopen(argv[1], "r");
      if (fpin == NULL) {
          fprintf(stderr, "Could not open input file %s (%s)\n",
                  argv[1], strerror(errno));
          return -1;
      }
  
      if ((names.files = malloc(10 * sizeof (char*))) == NULL) {
          fprintf(stderr, "Error allocating initial space for 2d array: %s\n",
                  strerror(errno));
          return -1;
      }
      names.maxfiles = 10;
  
      if (readInputFile(fpin, &amp;names) == -1) {
          fprintf(stderr, "Error reading image filenames from input\n");
          return -1;
      }
  
      threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t));
      threads_ids = (int*) malloc(num_images + 1 * sizeof (int));
  
      /* Initialize and set thread detached attribute */
      pthread_attr_init(&amp;attr);
      pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE);
      //creates requester thread, the 1st one on the list
      pthread_create(&amp;threads[0], &amp;attr, requester, &amp;threads_ids[0]);
      threads_ids[0] = 0;
  
      //creates so many converter threads as the number of images to convert
      for (i = 1; i &lt; num_images + 1; i++) {
          threads_ids[i] = i;
          rc = pthread_create(&amp;threads[i], &amp;attr, converter, &amp;threads_ids[i]);
          if (rc) {
              printf("ERROR; return code from pthread_create() is %d\n", rc);
              exit(-1);
          }
      }
  
  
      /* Free attribute and wait for the other threads */
      pthread_attr_destroy(&amp;attr);
  
      for (i = 0; i &lt; num_images + 1; i++) {
          printf("Waiting for thread nr %d\n", i);
          rc = pthread_join(threads[i], NULL);
          if (rc) {
              printf("ERROR; return code from pthread_join() is %d\n", rc);
              exit(-1);
          }
      }
  
      fclose(fpin);
      free(threads);
      free(threads_ids);
      printf("###########\n");
  
      deallocate2D(&amp;names);
  
      printf("Done!\n");
      return 0;
  }
  </code></pre>
  
  <p>This is one of the possible ouputs:</p>
  
  <pre><code>Num_lines: 10
  This is the requester thread
  Thread's id is: 1
  Thread's id is: 2
  Thread's id is: 3
  Thread's id is: 5
  Thread's id is: 4
  Thread's id is: 6
  Thread's id is: 7
  Thread's id is: 8
  Thread's id is: 9
  Waiting for thread nr 0
  Thread's id is: 10
  Segmentation fault
  </code></pre>
  
  <p>and this is the result of gdb:</p>
  
  <pre><code>Program received signal SIGSEGV, Segmentation fault.
  0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
  3724    malloc.c: No such file or directory.
      in malloc.c
  (gdb) where
  #0  0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
  #1  0x00120802 in *__GI__dl_deallocate_tls (tcb=&lt;value optimized out&gt;, 
      dealloc_tcb=112) at dl-tls.c:487
  #2  0x00133748 in __free_stacks (limit=41943040) at allocatestack.c:274
  #3  0x00133849 in queue_stack (pd=0xb5fd9b70) at allocatestack.c:302
  #4  __deallocate_stack (pd=0xb5fd9b70) at allocatestack.c:740
  #5  0x00134b37 in pthread_join (threadid=3053296496, thread_return=0x0)
      at pthread_join.c:110
  #6  0x0804955c in main (argc=4, argv=0xbffff4a4) at main.c:261
  </code></pre>