1

This code is raising segmentation fault, I'm not entirely where I did wrong. As soon as I input a string, it causes a segmentation fault. I was expecting it to append a new string in a new element of the char array.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char** append(char** b, size_t* size, char target[]);
int main(){
    size_t size = 1;
    char** b = malloc(sizeof(char)*size);
    while(1){
      char input[100] = "";
      scanf("%99s", input);
      if (strcmp(input, "end") == 0)
          break;
      b = append(b, &size, input);
    }
    for(int i = 0; i < size; i++)
        printf("%s ", b[i]);
    return 0;
}
char** append(char** arr, size_t* size, char target[]){
    *size += 1;
    size_t b = *size;
    char** new_arr = realloc(arr, b * sizeof(char));
    strcpy(new_arr[b - 1], target);
    return new_arr;
}
Izzuddin667
  • 83
  • 10
  • 1
    [Don't cast malloc result](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc#:~:text=You%20don't%20cast%20the%20result%20of%20malloc%20%2C%20because%20doing,don't%20take%20a%20guess.) `char **b` should be `char *b` – Ôrel Jan 26 '21 at 11:33
  • Do you want an array of strings, or to append strings one after the others ? – Ôrel Jan 26 '21 at 11:36
  • why is this the case? I want to make a 2D char array – Izzuddin667 Jan 26 '21 at 11:38
  • Yes i want to have an array of strings, where I can append a new string into it – Izzuddin667 Jan 26 '21 at 11:39
  • 2
    @Izzuddin667 This statement scanf("%s", input); invokes undefined behavior because the pointer input is not initialized. – Vlad from Moscow Jan 26 '21 at 11:42
  • After applying the changes, it's still giving a segmentation fault. – Izzuddin667 Jan 26 '21 at 11:48
  • 1
    Read [*Modern C*](https://modernc.gforge.inria.fr/) and [this C reference](https://en.cppreference.com/w/c). See [this answer](https://stackoverflow.com/a/41410503/841108) for an alternative approach. Read the documentation of your C compiler (e.g. [GCC](http://gcc.gnu.org/), to be used as `gcc -Wall -Wextra -g`...) and of your debugger (e.g. [GDB](https://www.gnu.org/software/gdb/)...). You could be interested in [valgrind](http://valgrind.org/) – Basile Starynkevitch Jan 26 '21 at 11:49
  • `char** lalala = malloc(sizeof(char) * size)` FAQ are getting really tiresome. Do we have a canonical dupe for these? They are very frequent. – Lundin Jan 26 '21 at 13:37
  • OT: regarding: `char** b = malloc(sizeof(char)*size);` 1) the expression: `sizeof(char)` is defined in the C standard as 1. Multiplying anything by 1 has no effect. suggest removing that expression. 2) always check (!=NULL) the returned value to assure the operation was successful. If not successful (==NULL) then call `perror( "malloc failed" );` to output both your error message and the text reason the system thinks the error occurred to `stderr`. – user3629249 Jan 27 '21 at 13:18
  • OT: regarding: `char** new_arr = realloc(arr, b * sizeof(char));` 1) see prior comment about `sizeof( char )` 2) when calling `realloc()` do not assign the result directly to the target pointer. (realloc can fail) rather assign to a temp variable, check that the `temp` variable is not NULL. If NULL, handle error, otherwise assign temp to the target variable – user3629249 Jan 27 '21 at 13:24
  • regarding>: ` if (strcmp(input, "end") == 0) break; b = append(b, &size, input); } for(int i = 0; i < size; i++) printf("%s ", b[i]);` what happens when the first string input is `end`? – user3629249 Jan 27 '21 at 13:28
  • the posted code will never work. For a 2d array of strings The "main' first item allocated needs to be an array of pointers to `char` Then each time an new string is to be added, realloc the 'first item' to be 1 pointer longer, then set the new/additional pointer to point to the new string. Perhaps via a `malloc()` + `strcpy()` or perhaps via a `strdup()` – user3629249 Jan 27 '21 at 13:33

1 Answers1

0

Keeping your logic to have one last empty element. You want an array of char * so you need to allocate size * sizeof(char *)

You need memory for scanf and check the returned value Then you need to copy the scan string, using strdup for example

A list can be better for your case

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char** append(char** b, size_t* size, const char* target);
int main(){
    size_t size = 1;
    char** b = malloc(sizeof(char*)*size);
    while(1){
      char input[256];
      int res = scanf("%s", input);
      if (res == EOF || strcmp(input, "end") == 0)
          break;
      b = append(b, &size, input);
    }
    for(int i = 0; i < size; i++)
        printf("%s ", b[i]);
    printf("\n");
    return 0;
}
char** append(char** arr, size_t* _size, const char* target){
    size_t size = *_size;
    arr[size - 1] = strdup(target);
    size++;
    char** new_arr = realloc(arr, size * sizeof(char *));
    *_size = size;
    return new_arr;
}
Ôrel
  • 7,044
  • 3
  • 27
  • 46