csegmentation-faultdynamic-memory-allocationrealloc

Problems with memory allocation and input (C)


My goal is to read input from the user and store each word given by the user in a dynamically allocated array which I called "str". However, I have two problems. One, in the function leArgs when reading an argument after the first one, if I try to print it using arg[agrs] (args > 0) it gives me SEGFAULT. Second, if I only give 1 word, the leArgs works, but it doesn't store anything in "str", giving me SEGFAULT after I try to print its first argument.

If I was confusing or not clear enough comment and I will rewrite it! My code:

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


    #define INVERSO "inverso"   /* String representativa da chave para impressão
                                do percurso duma carreira por ordem inversa */
    #define LEN_INVERSO 8       /* Comprimento da chave representativa */

    #define TRUE 1  /* verdadeiro */
    #define FALSE 0 /* falso */

    #define FIM_LINHA -1 /* fim de linha */
    #define NOTVALID -1 /* não é valido*/

    #define BUFFER 65535 

    enum arg {PRIMEIRO, SEGUNDO, TERCEIRO, QUARTO, QUINTO};


    int is_space ( int c ) {
        return (c == '\t' || c == ' ' || c == '\n'); 
    }

    /* Recebe um char e retorna True se for um fim de linha
    e false caso contrario */
    int NotEndOfLine ( char character ) {
        return character != '\n';
    }

    int leNome ( char *buff ) {
        int character, aspas = FALSE, i = 0;

        while ( is_space (character = getchar()) ) {
            if ( !NotEndOfLine(character) )
                return FIM_LINHA;
        }

        do {
            if (character == '"')
                aspas = (aspas == FALSE) ? TRUE : FALSE;
            else
                buff[i++] = character;

        } while ( !is_space(character = getchar() ) || aspas == TRUE );

        buff[i++] = '\0';

        return !NotEndOfLine ( character );
    }

    int leArgs ( char **arg ) {
        int num_args = 0, args = PRIMEIRO, lenght, endline;
        char buff[BUFFER];


        do {
            endline = leNome( buff );
            printf("Run: %d\n" , args);
            if ( endline == FIM_LINHA )
                return num_args;

            arg = (char**) realloc ( arg, sizeof (char*) * (++num_args)) ;

            lenght = strlen(buff);

            arg[args] = (char *) malloc (sizeof (char) * (lenght + 1) );
            strcpy( arg[args] , buff );
            
            printf("buff:%s arg:%d num_args:%d\n", buff, args, num_args);
            printf( "Argumento: %s\n", arg[args] );
            putchar('\n');
            args++;

        } while ( endline == FALSE ) ;

        return num_args;
    }

    int main(){
        int i, num_args;
        char **str = NULL;
        num_args = leArgs( str );

        printf( "%s ", str[0]);

        puts( "sucesso ");

        for(i = 0; i < num_args; i++){
            printf("i:%d",i);
            printf("%d:%s\n",i,str[i]);
        }

        return 0;
    }

Solution

  • You are passing the pointer str to the function leArgs by value

        char **str = NULL;
        num_args = leArgs( str );
    

    It means that the function deals with a copy of the original pointer. Changing the copy within the function does not change the original pointer.

    You need to pass it by reference through a pointer to it.

    That is the function should be declared like

    int leArgs ( char ***arg );
    

    and called like

    num_args = leArgs( &str );
    

    Within the function you need to write at least like for example

    *arg = (char**) realloc ( *arg, sizeof (char*) * (++num_args));
    

    though it will be safer to use an intermediate pointer like for example

    char **tmp = realloc ( *arg, sizeof (char*) * (++num_args));
    
    if ( tmp != NULL ) *arg = tmp;