1

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;
}
brec9824
  • 13
  • 3
  • 2
    You probably mean to use `(*args)` everywhere you use `args` in `parseCommand`... – user253751 Sep 29 '15 at 02:56
  • you have now become a 'three star programmer' Google 'threestarprogrammer'. strongly suggest passing the address of an int variable (argc) rather than passing the address of a char** variable (argv) and returning the argv pointer rather than the argc pointer – user3629249 Sep 30 '15 at 08:32
  • regarding this code block: `if (!args){printf("Allocation failed");}` Since the allocation failed, there is absolutely not reason to be trying to access that allocation. If the code does try to access that failed allocation, it will actually be accessing address 0, which when using any OS will result in a seg fault event. I.E. send the error info to stderr, then free any prior allocations, then exit – user3629249 Sep 30 '15 at 08:40
  • the parsing of the string into arguments, for the posted code, will fail when there is more than one space between arguments in the string. – user3629249 Sep 30 '15 at 08:44

1 Answers1

0

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.

Dmitri
  • 9,175
  • 2
  • 27
  • 34
  • Fixed that in my code and it works perfectly now. Also thanks for the explanation makes allot more sense now. – brec9824 Sep 29 '15 at 03:18