Hello. I need to set up some pipes for a homework assignment as part of a bigger project. The issue I'm having is that the array (args) I'm using to populate the pipe arguments keeps segfaulting and I don't know why. Everything has been malloced beforehand and the faults only occur at the mentioned places. Below, the relevant code:

char** args;
char** pipe1_args;
int pipe1_args_size;
char** pipe2_args;
int pipe2_args_size;

while (temp_std_command && array_size <= 255) //take args and break them up into an array
        {
            args[i] = malloc(sizeof(char)*255);
            strcpy(args[i], temp_std_command);
            temp_std_command = strtok(NULL, " ");
            i++;
            array_size++;
        }
        i++;
        array_size++;
        args[i] = malloc(sizeof(char)*255); //terminate array with null
        args[i] = NULL;

else    
        {
            pid_t pid; //Variables for creating new processes and waiting on created processes
            int status;
            pid_t pipe_pid;
            i = 0;
            pid = fork();   //Spawn new process
            if (pid < 0)
                perror("Fork"); //If error creating process, print out error
            else if (pid == 0) //Otherwise if child process, run execlp for external commands
            {   
                i = 0;
                for (i; i < array_size; i++) //checks for i/o redirect
                {
                    if(strcmp(args[i], "<") == 0) //input; set read to true and null out unneccesary fields
                    {               //terminate loop and copy filename for io
                        printf("read\n");
                        read = 1;
                        args[i] = NULL;
                        strcpy(io_filename, args[i+1]);
                        args[i+1] =NULL;
                        i = 0;
                        for (i; i < (array_size - 1); i++)
                            printf("Args: %s \n",args[i]);
                        i = array_size;
                    }               
                    else if(strcmp(args[i], ">") == 0) //output; set write to true and null out unneccesary fields
                    {               //terminate loop and copy filename for io
                        write = 1;
                        args[i] = NULL;
                        strcpy(io_filename, args[i+1]);
                        args[i+1] =NULL;
                        i = 0;
                        for (i; i < (array_size - 1); i++)
                            printf("Args: %s \n",args[i]);
                        i = array_size;
                    }
                }
                if (read == 1) //if read, replace stdin with file
                    {
                        int io_file;
                        io_file = open(io_filename, O_RDONLY);
                        if (io_file == -1)
                        {
                            perror("open");
                            return CHILD_ERROR;
                        }
                        if ( dup2( io_file, fileno(stdin)) < 0)
                        {
                            perror ("dup2");
                            return CHILD_ERROR;
                        }
                        fflush(stdout);
                        close(io_file);
                    }
                if (write == 1) //if write replace stdout with file
                    {
                        int io_file;
                        io_file = open(io_filename, O_WRONLY | O_CREAT, S_IRWXU);
                        if (io_file == -1)
                        {
                            perror("fopen");
                            return CHILD_ERROR;
                        }
                        if ( dup2( io_file, fileno(stdout)) < 0)
                            perror ("dup2");
                        fflush(stdout);
                        close(io_file);
                    }
                else
                {}
                i = 0;
                for (i; i <= array_size; i++) //checks for pipes
                {
                    if(args[i] != NULL && strcmp(args[i], "|") == 0) //pipe. Copy pipe args to two arrays, set up the pipes and
                    {           //call the second pipe function before the first
                        pipe_ = 1;
                        int pipe_index = i;
                        for (j; j < pipe_index; j++)
                        {
                            printf("%d \n",j);
                            pipe1_args[j] = malloc(sizeof(char)*255);
                            strcpy(pipe1_args[j],args[j]); //segfault
                            pipe1_args_size++;
                        }
                        j++;
                        pipe1_args_size++;
                        pipe1_args[j]=NULL;
                        j = pipe_index + 1;
                        for (j; j < (array_size - 1); j++)
                        {
                            pipe2_args[j-(pipe_index+1)] = malloc(sizeof(char)*255);
                            strcpy(pipe2_args[j-(pipe_index+1)],args[j]); //segfault
                            pipe2_args_size++;
                        }

That's simple enough: args is an uninitialized pointer, not a pointer to infinite memory. To simulate a 2D array you need to first allocate room for the number of pointers you want, then allocate memory to each pointer. Same thing with pipe_args.

The pattern is this:

char **args = malloc(10 * sizeof *args); // Allocate 10 pointers to char

for (int i = 0; i < 10; i++) {
    args[i] = malloc(255 * sizeof *args[i]); // Allocate a string of 254

    // Populate args[i] with a string and terminate it with '\0'
}

// Use args in your program's logic

// Clean up your mess
for (int i = 0; i < 10; i++) {
    free(args[i]);
}

free(args);

The long and short of it is that if you have a pointer, it must point somewhere. If you don't tell it where to point, your code is broken and will probably segfault.

This is the part where I allocate the variables:

int command_length = strlen(command) + 1; //allocate buffers for external commands
        char* temp = malloc(sizeof(char)*255);
        char* new_cmd = malloc(sizeof(char)*255);
        args = malloc(sizeof(char*)*255);
        char* exec_command = malloc(sizeof(char)*command_length);
        char* temp_std_command = malloc(sizeof(char)*command_length);
        char* io_type = "<>";
        char* command_io_type;
        char* io_filename = malloc(sizeof(char)*255);
        pipe1_args = malloc(sizeof(char*)*255);
        pipe2_args = malloc(sizeof(char*)*255);
        int read = 0;
        int write = 0;
        int pipe_ = 0;
        int array_size = 0;
        strncpy(exec_command,command,command_length);
        exec_command[command_length-1] = '\0';

        strncpy(temp_std_command,command,command_length);
        temp_std_command[command_length-1] = '\0';
        temp_std_command = strtok(temp_std_command, " ");
        int i = 0;
        int j = 0;
        while (temp_std_command && array_size <= 255) //take args and break them up into an array
        {
            args[i] = malloc(sizeof(char)*255);
            strcpy(args[i], temp_std_command);
            temp_std_command = strtok(NULL, " ");
            i++;
            array_size++;
        }
        i++;
        array_size++;
        args[i] = malloc(sizeof(char)*255); //terminate array with null
        args[i] = NULL;
This article has been dead for over six months. Start a new discussion instead.