I know this is a question that has been asked quite frequently but I have read 10+ closed questions without any luck as my solution seems to match those proposed as solutions by others.
I am writing my own shell as a learning exercise and in doing so, I am malloc'ing an array of strings to serve as the arguments of a program call. My malloc is done as follows where argcnt is the number of arguments given + 2 to match the standard argv size and allow the array to be null terminated and thus used by execvp:
char ** args;
args = (char **) malloc(argcnt*sizeof(char *));
for(i = 0; i < argcnt; i++) {
args[i] = (char *) malloc(80*sizeof(char));
printf("Made %d\n", i);
}
I then free the same memory as follows:
for (i = 0; i < argcnt; i++) {
free(args[i]);
printf("Freed %d\n", i);
}
free(args);
The program compiles but fails at freeing argv[1] at runtime. The sample output of running the program and then calling ls -a -l
is as follows:
jack@ubuntu:~/myshell$ ./myshell
[30/03 23:34] # ls -a -l
Argcnt: 4
Made 0
Made 1
Made 2
Made 3
Arg[0]: ls
Arg[1]: -a
Arg[2]: -l
Arg[3]: (null)
Freed 0
*** Error in `./myshell': free(): invalid pointer: 0x0000000001a84c43 ***
Aborted (core dumped)
I have been wrestling with this for the last 2 hours and can't work out what is wrong so some insight into the problem would be very much appreciated.
EDIT: The function currently breaking my program is:
void breakargs(char * cmd, char ** args) {
char * tok = malloc(strlen(cmd)*sizeof(char)); //maximum token size is full cmd
char * str = malloc(strlen(cmd)*sizeof(char));
int i=1;
strcpy(str, cmd); //maintains integrity of cmd
args[0] = tok = strtok(str, " ");
while (tok != NULL)
{
args[i] = tok = strtok(NULL, " ");
i++;
}
args[i] = '\0';
free(tok);
}
2nd EDIT: The problem was my reassigning of the pointers made by my original malloc with strtok so that the original pointer reference was lost. Furthermore, my use of a definite string length for arguments could potentially lead to problems. The solution was to only malloc args[i] when I knew the length of the string that needs to be stored there, and then move the string into that memory location using strcpy instead of direct assignment as I had been doing. This maintains the integrity of the pointer reference and allows it to be freed correctly.