Shikai
Shikai

Reputation: 1

strcpy() segmentation fault in 2-dimensional char** array

I'm currently programming a shell which grabs input and stores it in a string (char*) array. To enable UNIX operations like pipelining, I want to be able to write commands like

echo this | function more | function2

To do this, I'm collecting the command and its arguments in a while loop, and try to copy all contents of the argument array into a new, 2-dimensional array which holds the entire command line, e.g. "ls -f -a". So far, this works, but then, I'm trying to reset the loop as soon as a "|" was found in the command line, ignore the "|", and begin a new loop doing the same thing until '\0' is found, which marks the end of the original input:

char* arguments[MAXARGS]; // holds argument components, e.g. "ls" or "-f"
char** arg_collection[MAXARGS][MAXARGS]; // supposed to hold command lines, e.g. "ls -f -a"
argc_current = 0; // iterator for the loop, counts arguments
col_iterator = 0; // iterator for amount of command lines
int sentinel = 1; // sentinel value for while loop
...

while(sentinel)
{
    arguments[argc_current] = (char*) malloc (sizeof(word)); // word is defined, just not listed on here - refers to the currently read command / argument
     strcpy(arguments[argc_current], word); // copy current word into arguments

    if(tokens[argc_current] == TOKEN_TERMINATOR || tokens[argc_curernt] == TOKEN_NULL)
    {
       sentinel = 0; // tokens holds information about the type of word, e.g. if it is '\0'
    }

    if(tokens[argc_current] == T_BAR) // if the word is "|"
    {
       for(i = 0; i < argc_current; i++)
       {
          strcpy(arg_collection[col_iterator][i], arguments[i]); // copy argument list into collection
       }

       col_iterator++; // increment command line counter
       argc_current = 0; // reset argument counter, restart the loop
    }

    else
    {
        arg_current++; // increment current argument counter
    }
}

evaluating arguments here..

The first loop works fine, e.g. if I type

echo this | echo more |

It fills arg_collection[0][0] and arg_collection[0][1], so I get "echo this" as a result. After having incremented col_iterator to 1, however, I hit a brick wall in form of a segmentation fault when calling strcpy upon noticing the second "|". Why?

Upvotes: 0

Views: 656

Answers (2)

silen
silen

Reputation: 534

First you should allocate arg_collection before using it. (As you don't give the entire code, I assume you don't do it).

Then you are dereferencing two times your arg_collection on line:

strcpy(arg_collection[col_iterator][i], arguments[i]); // copy argument list into collection

When you must

strcpy(arg_collection[col_iterator], arguments[i]); 

That is, you are treating the char at index i of string col_iterator in arg_collection as char *, when it is only a char.

Upvotes: 0

simonc
simonc

Reputation: 42185

It looks like word is a char*. If so, you should change

arguments[argc_current] = (char*) malloc (sizeof(word));

to

arguments[argc_current] = malloc(strlen(word)+1);

sizeof(word) will give you the size of a pointer variable, not the size of the data it points to. strlen tells you the number of characters in word. The +1 is needed for the '\0' terminator.

Upvotes: 2

Related Questions