-1

I have 2D array I want populate then compare to literal

below is compare code, i try different things with no success

char** list;

load(list);

if(strcmp(list[0], "aasdf"))
{
    printf("win\n");
}

the above segfaults on strcmp

load function

void load(char **list)
{
int MAX_NUM_LINES = 1000;

FILE *fp;

list = malloc(MAX_NUM_LINES*sizeof(char*));
fp = fopen("list", "r");

line_ct = 0;
char line[256];
while ( fgets(line, 256, fp) != NULL )
{
   int len = strlen(line);
   list[line_ct] = malloc(len * sizeof(char));
   strcpy(list[line_ct], line);
   line_ct++;

   if(line_ct == MAX_NUM_LINES)
   {
        break;
   }
}

fclose(fp);
}

any ideas on why is segfault?

also i try before strcmp

printf("Line: %s\n", *list[0]);

it segfault to

  • 2
    `malloc(len * sizeof(char));` -> `malloc(len + 1);` (need extra char for string terminator). – Paul R Jun 29 '19 at 07:25
  • @RomanianStrife I was editing my answer when you accepted it, read it again for more ;-) – bruno Jun 29 '19 at 07:59

1 Answers1

1

when you come back from load the var list is not set, so when you do

 if(strcmp(list[0], "aasdf"))

you have an undefined behavior using list (typically a crash)


The first solution is use an output var

you need to change

load(list);

by

load(&list);

and you need to change the type of list and dereference it in load, so :

void load(char ***list)
{
  *list = malloc(MAX_NUM_LINES*sizeof(char*));
  ...
  (*list)[line_ct] = malloc((len + 1) * sizeof(char));
  strcpy((*list)[line_ct], line);

I also added 1 to len to have place for the ending null character.

(edit) The use of a *** is not very common, as suggested by @user3629249 in a remark you can look at Triple pointers in C: is it a matter of style? reading carefully the answers.


The second solution is to return the allocated array :

char** list = load();

with

char ** load()
{
   char **list;
   ...
   return list;

also adding 1 to len when you allocate each line


Out of that if you read more than MAX_NUM_LINES lines you write out of the array again with an undefined behavior, and the caller of load does not know how much lines you read.

To avoid that you can first initialize list with malloc(0) then use realloc to increase the size of list each time you read a line, that allows to allocate the right size. To indicate the size to the caller you can use an additional output var or to allocate one entry more to place NULL in the last entry (all depends on how you use the read array in the code calling load)

bruno
  • 32,421
  • 7
  • 25
  • 37
  • using: `void load(char ***list)` is a very bad idea. suggest reading: [three star programmer](http://don.fed.wiki.org/view/three-star-programmer) – user3629249 Jun 29 '19 at 17:28
  • @user3629249 yes and no, but as you can see I also propose to not use that way and return the value which is more practical. Note in my answer I propose first the *** to follow the use of a parameter as the OP, not because I prefer that way ;-) Your link is out of S.O., if you find one equivalent in S.O. I edit my answer to add it ^^ – bruno Jun 29 '19 at 17:35
  • Since most discussion about three star programmers is (somewhat) negative, The PC freaks have remove (almost) all the related documents. Here is a link inside SO: [three star programmer](https://stackoverflow.com/questions/21488544/triple-pointers-in-c-is-it-a-matter-of-style) – user3629249 Jun 29 '19 at 17:52
  • @user3629249 I didn't found it (that means I did not search enough ^^), as promise I edited my answer to add it – bruno Jun 29 '19 at 18:06