Search code examples
clinuxshellxv6

Array of strings gets entirely rewrote when I try to append - C (xv6)


I am declaring an array of strings by using:

char *commands[100];

I then proceed to enter a while loop that reads commands input from the user:

    while(getcmd(buf, sizeof(buf), cmd_count) >= 0){

            printf(2, "cmd_count: %d\n", cmd_count);
            buf[strlen(buf)-1] = 0;
            printf(2, "string buf: -%s-\n", buf);
            commands[cmd_count] = buf;
            printf(2, "commands: %s\n", commands[0]);
            printf(2, "commands: %s\n", commands[1]);
            printf(2, "commands: %s\n", commands[2]);
            printf(2, "commands: %s\n", commands[3]);
            cmd_count++;
    }

Here is the output from two iterations:

0 EZ$ ls
cmd_count: 0
string buf: -ls-
commands: ls
commands: (null)
commands: (null)
commands: (null)

EZ$ echo hello
cmd_count: 1
string buf: -echo hello-
commands: echo hello
commands: echo hello
commands: (null)
commands: (null)

Even though cmd_count was clearly 1 on the second iteration, it rewrote both the 0th and 1st position. What gives?


Solution

  • Not knowing your entire algorithm, a simple approach may be:

    • currently you have the variable command allocated to hold 100 char pointers, so that gives you room to handle cmd_count 0 - 99.

    • but you only have a single buffer for storing each command

    • if you do need to store each command past the while loop in which you read them, how about the following approach:

    allocate a buffer for each pointer in commands that is big enough to hold a command

    for (int i = 0; i < 100; i++) {
        commands[i] = malloc(MAXSTRINGSIZE + 1);
    }
    

    (you could probably optimize this by allocating ((MAXSTRINGSIZE + 1) * 100) and then setting each pointer in commands to the correct offset, but the approach above may be easier for you to understand if you are just learning about pointers)

    • And then try replacing buf in the getcmd() call with commands[i], so that you read the command directly into an entry in the commands array.