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.

Thanks.

#include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    
    #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 *args[MAX_ARGS_NUMBER];	
    	
    	int i = 0;
    	arg = strtok(cmd_line, " ");
    	while (arg != NULL) {
    		args[i] = 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 < num_elems; i++)
    	{					
    		if ( !strcmp(args[i], "<") )
    		{				
    			if ( b_infile || i == num_elems-1 || !strcmp(args[i+1], "<") || !strcmp(args[i+1], ">") || !strcmp(args[i+1], "&") )
    				return -1;						
    
    			i++;
    			cmd_info->infile = malloc(strlen(args[i]) * sizeof(char));
    			strcpy(cmd_info->infile, args[i]);
    			b_infile = true;
    		}
    		
    		else if (!strcmp(args[i], ">"))
    		{
    			if ( b_outfile || i == num_elems-1 || !strcmp(args[i+1], ">") || !strcmp(args[i+1], "<") || !strcmp(args[i+1], "&") )
    				return -1;
    			
    			i++;	
    			cmd_info->outfile = malloc(strlen(args[i]) * sizeof(char));
    			strcpy(cmd_info->outfile, args[i]);
    			b_outfile = true;
    		}
    		
    		else if (!strcmp(args[i], "&"))
    		{
    			if ( i == 0 || i != num_elems-1 || cmd_info->background )
    				return -1;
    
    			cmd_info->background = true;
    		}
    		
    		else
    		{
    			cmd_info->arg[iarg] = malloc(strlen(args[i]) * sizeof(char));
    			strcpy(cmd_info->arg[iarg], args[i]);
    			iarg++;
    		}
    	}
    		
    	cmd_info->arg[iarg] = NULL;	
    
    	return 0;
    }
    
    
    void print_cmd(Command_Info *cmd_info)
    {
    	int i;	
    	for (i = 0; cmd_info->arg[i] != NULL; i++)
    		printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);
    	printf("arg[%d]=\"%s\"\n", i, cmd_info->arg[i]);	
    	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);
    	str[strlen(str)-1] = '\0';
    }
    
    pid_t exec_simple(Command_Info *cmd_info)
    {
    	pid_t pid = fork();
    
    	if (pid < 0)
    	{
    		perror("Fork Error");
    		return -1;
    	}
    
    	if (pid == 0)
    	{
    		if ( (execvp(cmd_info->arg[0], cmd_info->arg)) == -1)
    		{
    			perror(cmd_info->arg[0]);
    			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->arg[i] != NULL; i++)
    		free(cmd_info->arg[i]);
    	free(cmd_info->arg);
    	free(cmd_info->infile);
    	free(cmd_info->outfile);
    }
    
    int main(int argc, char* argv[])
    {
    	char cmd_line[MAX_COMMAND_LENGTH];
    	Command_Info cmd_info;
    	//char* history[MAX_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.arg[0], "exit"))
    			exit(0);
    
    		pid_t pid = exec_simple(&cmd_info);
    
    		waitpid(pid, NULL, 0);
    		
    		free_mem(&cmd_info);
    	}
    
    	return 0;
    }

> cmd_info->infile = malloc(strlen(args) * sizeof(char));
You need strlen(x) + 1 chars to copy a string.

Why is it needed one more char? Because of '\0'?

Anyway, I have changed that in the code and still get the some error as before.

Any more ideas?

Thanks.

This question has already been answered. Start a new discussion instead.