davidhood2
davidhood2

Reputation: 1367

Losing contents of char**array when passed to function in C

I have the following structs in my on-going struggle to eventually create some kind of shell (based eventually around execvp().

struct commands {
    char cmdname[30]; // The name of the command
    enum ActionType action; /* char action[30];  what action to take */
};

struct userinput {
    struct commands theaction; //The chosen action
    char cmdentered[100]; // The cmd entered
    char **anyargs; //The tokenised command
    int argcount; //Argument count
};

And I initialise anyargs using malloc and create an array of strings with one string per argument to be passed on to the execvp.

I then get user input, convert the input into tokens stored in anyargs and examine the strings to find out what sort of action needs to be taken and store that in an enum.

All these methods are done by passing the pointer to the struct userinput as method parameters - which works fine. HOWEVER when I pass the pointer to the struct to a nested function, the char** anyargs becomes empty.

I hope the code I've added provides a solution to the answer! On another observation - when passed to a function inside a function, the actual value of the pointer doesn't change - only the dereferenced contents of the pointer.

Any help would be most gratefully received! I've tried to strip the code down to the areas I think are causing the issue! Thank you!

int main() {

    struct commands cmdlist[4]; //Array of structures with all commands in them
    memset(cmdlist, 0, sizeof(cmdlist));

    struct userinput userentry = { { { 0 } } }; //Structure containing input
    userentry.theaction = cmdlist[0]; //Initialize empty command
    userentry.anyargs = calloc(100, sizeof(char));

    runEntry(&userentry, cmdlist); //Pass struct to function 

    free(userentry.anyargs);

    return 0;
}

int runEntry(struct userinput *userentry, struct commands thecmds[]) {
    int retval = 0;
    int childpid = 0;
    int processStatus;
    printf("\n    ... running cmd: \n\n");

    printUserEntry(userentry); //in printUserEntry, 
                               //userentry->anyargs[0] = NULL - why?
}

Upvotes: 0

Views: 1053

Answers (1)

Paul Roub
Paul Roub

Reputation: 36438

You've allocated 100 bytes worth of char * elements in anyargs. You haven't initialized those pointers, though. The fact that anyargs[0] happens to contain NULL is nice, but not guaranteed. malloc() doesn't initialize the allocated space.

In other words, when you say:

userentry.anyargs = malloc(100);

you've created:

userentry.anyargs = {
  ???, // uninitialized char * 
  ???, // and another
  ???, // and another
  ...
  ???  // (100 / sizeof(char *)) entries later
};

You can explicitly initialize those to NULL in a loop:

for ( i = 0; i < (100 / sizeof(char *)); ++i )
  userentry.anyargs[i] = NULL;

(or use calloc() instead of malloc() to ensure everything is zeroed out).

or you can allocate some space to them:

for ( i = 0; i < (100 / sizeof(char *)); ++i )
  userentry.anyargs[i] = malloc(50);  // or some other length

or just set them directly in runEntry():

userentry.anyargs[0] = "foo";
userentry.anyargs[1] = strdup(something);

Upvotes: 1

Related Questions