Search code examples
cpointersdynamic-allocation

C dynamic allocated pointer to main function


I cant figure out how to have my pointer argv maintain its memory that I dynamically allocate in another function called parseCommand. I need to call parseCommand, allocate the needed memory for the parsed strings and then return to main and print the strings my pointer points to. I would just have parseCommand return the pointer but I have to return the number of arguments found. I haven't really worked to much with c pointers so they are giving me some trouble here. So how do I go about having my pointer maintain its memory between functions?

Main:

int main()
{
    char **argv, str[] = "ls -l -s -r -h file";
    int argc;

    argc = parseCommand(str, &argv); 

    int i;
    printf("Arguments in argv: \n");
    for (i = 0; i < argc; i++)       //I want to output the arguments
        printf("%s \n", argv[i]);    //stored in pointer argv

    return 0;
}

My parse function that dynamically allocates memory for my pointer so it can store the arguments in str.

Parse Command:

int parseCommand(char *str, char ***args)
{
    int i = -1, prevPos = 0, argc = 0, argl = 0, argCount = 0;
    argCount = getArgCount(str); //Returns 6

    args = malloc(sizeof(char*) * (argCount + 1));                  /*Allocates memory for args in amount of arguments str holds*/
    if (!args){printf("Allocation failed");}                        /*Checks if there was a problem with memory allocation*/

    do
    {
        i++;
        if (str[i] == ' ' || str[i] == '\n' || str[i] == '\0')
        {
            argl = (i + 1) - prevPos;                                /*argl holds the length of the argument*/
            args[argc] = malloc(sizeof(char) * argl);                /*Allocates memory for args in the size of the argument*/
            if (!args[argc]){printf("Allocation failed");}           /*Checks if there was a problem with memory allocation*/

            memcpy(args[argc], str + prevPos, argl);                 /*Copys the argument of the string into args*/
            args[argc][argl - 1] = '\0';                             /*Assigns \0 at the end of the string*/

            argc++;
            prevPos = i + 1;
        }
    } while (str[i] != '\0');

    args[argc] = malloc(sizeof(char));                               /*Allocates one last piece of memory for args*/
    args[argc][0] = (char *)NULL;                                    /*Sets this new piece of memory to NULL*/

    printf("Arguments in args: \n");
    for (i = 0; i < argc; i++)
         printf("%s \n", args[i]);

    return argCount;
}

Solution

  • In parseCommand(), args is char *** but you're treating it like char **. You need to dereference it once to get the char ** that you'll have in main(). For example, this:

    args = malloc(sizeof(char*) * (argCount + 1));
    

    ..should be:

    *args = malloc(sizeof(char*) * (argCount + 1));
    

    And this:

    args[argc] = malloc(sizeof(char) * argl);
    

    ..should be:

    (*args)[argc] = malloc(sizeof(char) * argl);
    

    and these lines:

    memcpy(args[argc], str + prevPos, argl);
    args[argc][argl - 1] = '\0';
    

    ..should be:

    memcpy((*args)[argc], str + prevPos, argl);
    (*args)[argc][argl - 1] = '\0';
    

    etc.

    args from parseCommand() does not point at the array of char * for the argument strings -- it points to argv from main(), and that points to the array of char * for the argument strings... so you need to dereference args once before using it.