Segmentation fault when using strcpy on double pointer

705 views Asked by At

I'm pretty new to C, but have programmed a great deal in both Java and Python. So I got the basics going – however, C keeps hitting me with this Segmentation fault: 11 no matter how I wrap my head around my code. I suspect the problem may be that I'm accessing beyond the bounds of my array, namely in this part:

ordListe[i] = (char*)malloc(n);
strcpy(ordListe[i], ord);

For hours I've been at a loss how to solve this, so now I turn to you: what am I missing? I couldn't find many posts involving pointers to pointers out there with a similar problem, so i assume this will be of some help to others in the future too. Full function where the problem occurs:

char** split(char* s)
{
  char* setning = (char*) malloc(strlen(s) + 1);
  strcpy(setning, s);  //Setning blir det samme som s, saa vi slipper aa roere s
  printf("%s\n", setning);  //TNB: Feilsoeking
  char* ord = (char *) malloc(strlen(setning) * sizeof(char));  //Henter ut ordet
  ord = strtok(setning, " ");  //Henter foerste ord
  printf("%s", ord);
  int i = 0;
  size_t n = 0;
  char** ordListe = (char**) malloc(strlen(s) * sizeof(char));  //Lager en liste vi kan lagre verdiene i
  ordListe[strlen(setning)+1] = NULL;
  while(ord != NULL)
  {
    n = strlen(ordListe[i]) + 1;
    ordListe[i] = (char*)malloc(n);
    strcpy(ordListe[i], ord);
    i++;
    ord = strtok (NULL, " ");  //Beveger den videre
  }
  free(setning);
  return ordListe;
}

The purpose of the function is to split a string and store the individual parts in a pointer-to-pointer array and return said array. Thanks in advance!

1

There are 1 answers

0
Mahonri Moriancumer On

Here is one way to do it:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

/****************************************************************
**
*/
char **split(const char *s)
   {  
   char  *setning  = NULL;
   char  *ord      = NULL;
   char **ordListe = NULL;
   int    elements = 0;
   char **new;

   /* Build non-const version of the input string. */
   errno=0;
   setning = strdup(s);
   if(!setning)
      {
      fprintf(stderr, "strdup() reports: %d %s\n", errno, strerror(errno));
      goto CLEANUP;
      }

   /* Parse the string into an array of strings. */
   ord = strtok(setning, " "); 
   while(ord)
      {
      /* Increase the array of string pointers by one. */
      errno=0;
      new=realloc(ordListe, sizeof(char *) * (elements + 1));
      if(!new)
         {
         fprintf(stderr, "realloc() reports: %d %s\n", errno, strerror(errno));
         goto CLEANUP;
         }

      ordListe=new;

      /* Append an allocated string to the end of the array of strings. */
      ordListe[elements] = strdup(ord);
      if(!ordListe[elements])
         {
         fprintf(stderr, "strdup() reports: %d %s\n", errno, strerror(errno));
         goto CLEANUP;
         }

      ++elements;
      ord = strtok(NULL, " "); 
      }

   /* Add a NULL termination value to the end of the array of strings. */
   errno=0;
   new=realloc(ordListe, sizeof(char *) * (elements + 1));
   if(!new)
      {
      fprintf(stderr, "realloc() reports: %d %s\n", errno, strerror(errno));
      goto CLEANUP;
      }   

   ordListe=new;

   ordListe[elements] = NULL;

CLEANUP:

   /* Free the working copy of the string. */
   if(setning)
      free(setning);

   /* Free everything if there was an error, and return NULL. */
   if(errno)
     {
     while(elements)
        free(ordListe[elements--]);

     free(ordListe);
     ordListe=NULL;
     }

   return ordListe;
   }

/****************************************************************
** Program start.
*/
int main(int argC, char *argV[])
   {
   char **ordListe = NULL;
   char **iter = NULL;

   /* Split a string. */
   ordListe=split("Now is the time for all good men to come to the aid of their country.");
   if(!ordListe)
      {
      fprintf(stderr, "split() failed.\n");
      goto CLEANUP;
      }

   /* Print each split-out string. */
   iter = ordListe;
   while(*iter)
      {
      printf("%s\n", *iter);
      ++iter;
      }   

CLEANUP:

   /* Free the array of strings. */
   if(ordListe)
      {
      iter = ordListe;
      while(*iter)
         {
         free(*iter);
          ++iter;
         }

      free(ordListe);
      }

   return(0);
   }