Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can some tell me why I am seg faulting in this simple C program?

I keep on getting seg faulted after I end my first for loop, and for the life of me I don't why. The file I'm scanning is just 18 strings in 18 lines. I thinks the problem is the way I'm mallocing the double pointer called picks, but I don't know exactly why. I'm am only trying to scanf strings that are less than 15 chars long, so I don't see the problem. Can someone please help.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LENGTH 100

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

   char* string = malloc( 15*sizeof(char) );
   char** picks = malloc(15*sizeof(char*));
   FILE* pick_file = fopen( argv[l], "r" );
   int num_picks;


   for( num_picks=0 ; fgets( string, MAX_LENGTH, pick_file ) != NULL ; num_picks++ )
     {
       scanf( "%s", picks+num_picks );
     }
   //this is where i seg fault
   int x;
   for(x=0; x<num_picks;x++)
     printf("s\n", picks+x);
}
like image 286
user299648 Avatar asked Dec 03 '22 05:12

user299648


1 Answers

picks is a pointer-to-a-pointer: that means that the things it points to, are themselves pointers.

When you do this:

char** picks = malloc(15*sizeof(char*));

You are making picks point to a block of 15 pointers - which is fine as far as it goes (although, since you want to read in 18 lines, you really need 18 here instead of 15). This means that picks points to a block of variables in memory like this:

| picks (char **) | --------> | picks[0] (char *)  | ----> ?
                              | picks[1] (char *)  | ----> ?
                              | picks[2] (char *)  | ----> ?
                              | ...                |
                              | picks[14] (char *) | ----> ?

As you can see, those 15 char * pointers are now unintialised - they don't point to anything. You can't start using them until you allocate some memory for those, too - you need to do something like this:

int i;
for (i = 0; i < 15; i++)
{
    picks[i] = malloc(15);
}

Now, after that, the memory layout looks like this:

| picks (char **) | --------> | picks[0] (char *)  | ----> | picks[0][0] (char)  |
                                                           | picks[0][1] (char)  |
                                                           | ...                 |
                                                           | picks[0][14] (char) |

                              | picks[1] (char *)  | ----> | picks[1][0] (char)  |
                                                           | ...                 |

                              | ...                |

...and you now have places to store all those characters you want to read.

like image 149
caf Avatar answered Dec 11 '22 11:12

caf