Search code examples
carrayssegmentation-faultdynamic-memory-allocationrealloc

Segmentation fault when trying to read stdin to a 2d dynamically allocated array


I'm trying to read from stdin to a dynamic array of strings, using spaces as separators. The code is as follows

#include<stdio.h>
#include<stdlib.h>
char** parseInput(size_t *numElements)
{
  char **lines;
  int outerIndex = 0;
  int innerIndex = 0;
  int widths = 1;
  char c=getchar();
  lines =(char**) malloc((outerIndex+1)*sizeof(char*));
  lines[0] = (char*) malloc(sizeof(char));
  while(c!=EOF)
  {
    if(innerIndex==widths)//reallocate each strings length, double it
    {
      widths+=widths;
      int i;
      for(i=0;i<outerIndex+1;i++)
        lines[i]=(char*)realloc(lines[i],(widths+1)*sizeof(char));
    }
    lines[outerIndex][innerIndex]=c;
    innerIndex++;
    if(c==' ')//allocate memory for the next string in the array of strings
    {
      lines[outerIndex][innerIndex]='\0';
      innerIndex=0;
      outerIndex++;
      lines =(char**) realloc(lines,(outerIndex+1)*sizeof(char*));
      lines[outerIndex] = (char*) realloc(lines[outerIndex],(widths+1)*sizeof(char));
      //the above line in the debugger causes a segfault when outerIndex=19
    }
    c=getchar();
  }
  if(innerIndex!=0)//if the last character is not a space, append a space
  {
    if(innerIndex==widths)
    {
      widths+=widths;
      int i;
      for(i=0;i<outerIndex+1;i++)
        lines[i]=(char*)realloc(lines[i],(widths+1)*sizeof(char));
    }
    lines[outerIndex][innerIndex]=' ';
    lines[outerIndex][innerIndex+1]='\0';
  }
  *numElements=(size_t)(outerIndex+1);
  return lines;
}
int main()
{
    size_t num =0;
    char** lines = parseInput(&num);
}

When the outer array size grows to anything more than 20 variables, I get a segmentation fault at the indicated line. For example the following input causes a segfault

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

but the following does not

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

The debug error says

Program received signal SIGSEGV, Segmentation fault.
0x0000003417e7bf4d in realloc () from /lib64/libc.so.6

What could this be caused by?


Solution

  • On this line:

    lines[outerIndex] = (char*) realloc(lines[outerIndex], (widths+1)*sizeof(char));
    

    you supply an uninitialized pointer as the first argument to realloc. You should probably use malloc here instead.

    Other issues:

    • char c should be int c (read the documentation for getchar to see why).
    • If the input begins with a space then lines[outerIndex][innerIndex]='\0' writes out of bounds.
    • The code block starting if(innerIndex==widths) is repeated twice in your code; it would be better to either make this a function, or restructure your code so there is not this repetition.
    • You can simplify your malloc/realloc calls by removing redundant casts and the redundant multiplication by sizeof(char) which is always 1.
    • You should check malloc/realloc for failure and act accordingly.