Since strings in C are null-terminated, their actuall size in memory is length+1, so instead of.
Up vote 0 down vote favorite share g+ share fb share tw.
I need help with debugging this piece of code. I know the problem is in malloc and free but can't find exactly where, why and how to fix it. Please don't answer: "Use gdb" and that's it.
I would use gdb to debug it, but I still don't know much about it and am still learning it, and would like to have, in the meanwhile, another solution. Thanks. #include #include #include #include #include #include #include #define MAX_COMMAND_LENGTH 256 #define MAX_ARGS_NUMBER 128 #define MAX_HISTORY_NUMBER 100 #define PROMPT ">>> " int num_elems; typedef enum {false, true} bool; typedef struct { char **arg; char *infile; char *outfile; int background; } Command_Info; int parse_cmd(char *cmd_line, Command_Info *cmd_info) { char *arg; char *argsMAX_ARGS_NUMBER; int I = 0; arg = strtok(cmd_line, " "); while (arg!
= NULL) { argsi = arg; arg = strtok(NULL, " "); i++; } num_elems = i;precisa em free_mem if (num_elems == 0) return 0; cmd_info->arg = (char **) ( malloc(num_elems * sizeof(char *)) ); cmd_info->infile = NULL; cmd_info->outfile = NULL; cmd_info->background = 0; bool b_infile = false; bool b_outfile = false; int iarg = 0; for (i = 0; I ") ||! Strcmp(argsi+1, "&") ) return -1; i++; cmd_info->infile = malloc(strlen(argsi) * sizeof(char)); strcpy(cmd_info->infile, argsi); b_infile = true; } else if (!strcmp(argsi, ">")) { if ( b_outfile || I == num_elems-1 ||! Strcmp(argsi+1, ">") ||!
Strcmp(argsi+1, "outfile = malloc(strlen(argsi) * sizeof(char)); strcpy(cmd_info->outfile, argsi); b_outfile = true; } else if (!strcmp(argsi, "&")) { if ( I == 0 || I! = num_elems-1 || cmd_info->background ) return -1; cmd_info->background = true; } else { cmd_info->argiarg = malloc(strlen(argsi) * sizeof(char)); strcpy(cmd_info->argiarg, argsi); iarg++; } } cmd_info->argiarg = NULL; return 0; } void print_cmd(Command_Info *cmd_info) { int i; for (i = 0; cmd_info->argi! = NULL; i++) printf("arg%d=\"%s\"\n", i, cmd_info->argi); printf("arg%d=\"%s\"\n", i, cmd_info->argi); printf("infile=\"%s\"\n", cmd_info->infile); printf("outfile=\"%s\"\n", cmd_info->outfile); printf("background=\"%d\"\n", cmd_info->background); } void get_cmd(char* str) { fgets(str, MAX_COMMAND_LENGTH, stdin); strstrlen(str)-1 = '\0'; } pid_t exec_simple(Command_Info *cmd_info) { pid_t pid = fork(); if (pid arg0, cmd_info->arg)) == -1) { perror(cmd_info->arg0); exit(1); } } return pid; } void type_prompt(void) { printf("%s", PROMPT); } void syntax_error(void) { printf("msh syntax error\n"); } void free_mem(Command_Info *cmd_info) { int i; for (i = 0; cmd_info->argi!
= NULL; i++) free(cmd_info->argi); free(cmd_info->arg); free(cmd_info->infile); free(cmd_info->outfile); } int main(int argc, char* argv) { char cmd_lineMAX_COMMAND_LENGTH; Command_Info cmd_info; //char* historyMAX_HISTORY_NUMBER; while (true) { type_prompt(); get_cmd(cmd_line); if ( parse_cmd(cmd_line, &cmd_info) == -1) { syntax_error(); continue; } if (!strcmp(cmd_line, "")) continue; if (!strcmp(cmd_info. Arg0, "exit")) exit(0); pid_t pid = exec_simple(&cmd_info); waitpid(pid, NULL, 0); free_mem(&cmd_info); } return 0; } c memory-management memory-allocation free malloc link|improve this question asked Apr 17 '10 at 14:20nunos1,108627 96% accept rate.
– Daniel Rose Apr 17 '10 at 14:31 It doesn't say at which line... – nunos Apr 17 '10 at 14:42.
Since strings in C are null-terminated, their actuall size in memory is length+1, so instead of cmd_info->infile = malloc(strlen(argsi) * sizeof(char)); You should have cmd_info->infile = malloc((strlen(argsi)+1) * sizeof(char)); EDIT: As Aeth said, you need to change every single occurence of malloc to contain space for that additional null character: cmd_info->arg = (char **) ( malloc(num_elems * sizeof(char *)) ); //this one can stay, since it determines number of strings, not string length cmd_info->outfile = malloc((strlen(argsi)+1) * sizeof(char)); cmd_info->argiarg = malloc((strlen(argsi)+1) * sizeof(char)).
I have changed that, but still get the same error. What am I doing wrong? Please help.
Question edited. – nunos Apr 17 '10 at 14:46 Take a look at my answer and see if you are still having the same problems after doing the second step. – Matthew T.
Staebler Apr 17 '10 at 14:55 Thanks so much! It worked! – nunos Apr 17 '10 at 17:39 Glad to help :) – raceCh- Apr 17 '10 at 18:03.
You need to allocate an extra char for each of your strings to handle the terminating null. Cmd_info->argiarg = malloc((strlen(argsi)+1) * sizeof(char)); You need to allocate an additional char* in the cmd_info->arg array. This extra element will store the NULL that signifies the end of the array of arguments.
Cmd_info->arg = (char **) ( malloc((num_elems+1) * sizeof(char *)) ); I have confirmed on my system that the program successfully frees all its memory without error after both of the changes listed were made.
1, yes those two change should fix the program. Good findings :) – codaddict Apr 17 '10 at 14:58.
When you are dynamically allocating memory for cmd_info->infile as: cmd_info->infile = malloc(strlen(argsi) * sizeof(char)); you are not allocating space for the terminating null char. Same is the case with allocation for cmd_info->outfile When you allocate space for n char and copy a string of length n into it, I think that overwrites the metadata that malloc maintains at the end of the array and this bug shows up when you call free to deallocate the memory as free does not find that meta data. EDIT: Change: num_elems = i; to num_elems = i+1; Since you are marking the end of the arguments with NULL cmd_info->argiarg = NULL; you need to allocate the space for this.
In general, this error is usually the result of something writing data outside a malloc()'d block (off the end or before the beginning). This can corrupt the memory allocator's internal bookkeeping structures. Others have already pointed out the particular problem in your code.
In cases where it's more deeply hidden, I have found Valgrind to be useful for debugging. At the expense of noticable code slowdown, it is able to detect illegal memory accesses (in the form of "invalid reads" and "invalid writes") at a very fine-grained level. Memory debuggers such as dmalloc can also be helpful, and don't impose nearly as much overhead, but in my experience aren't quite as good as Valgrind for finding everything.
Valgrind, in its 'memcheck' mode, will output memory access errors with a stack trace of where in the program they occurred. Usually, when I have an "invalid pointer" error in free(), it will be preceeded at some point by an invalid write which memcheck will find.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.