0

I simplified my code as much as possible:

#define MAX_BUF 4096
#define MAX_ARGS 200

int main() {
    char **argv;
    argv = malloc(sizeof(char*)*MAX_ARGS);
    
    get_command(argv);

    printf("arg0:%s\n", argv[0]);
    cd(argv, NULL);
    printf("arg2:%s\n", argv[0]);
}

void cd(char *argv[], char *old_pwd) {
    char cwd[MAX_BUF];
    printf("arg1:%s\n", argv[0]);
}

void get_command(char *argv[]) {
    char input[MAX_BUF];

    fgets(input, sizeof(input), stdin);

    argv[0] = strtok(input, " ");
    argv[1] = strtok(NULL, " ");
}

get_command reads the input of the user, let's say it's aa bb, it would then save aa to argv[0] and bb to argv[1]. Let's note that argv is an array whose memory has been allocated dynamically inside main. Then, I pass argv to cd, but the elements of argv seem to change? The only thing I did there is declare a new string, and if I remove this declaration argv doesn't change and it works correctly. So my guess is that what I am doing is somehow undefined behavior, but I don't get how. Thank you in advance!

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
BillTheKid
  • 377
  • 1
  • 13
  • 1
    Because it's a pointer... – user202729 Dec 06 '21 at 10:15
  • Does this answer your question? [Passing an array as an argument to a function in C](https://stackoverflow.com/questions/6567742/passing-an-array-as-an-argument-to-a-function-in-c) – user202729 Dec 06 '21 at 10:16
  • 6
    Be aware that all pointers to the local variable `input` in `get_command` will point to garbage as soon as the `get_command` has ended. Local variables cease to exist as soo as their function is over. – Jabberwocky Dec 06 '21 at 10:18
  • @user202729 even if I replace ```*argv[]``` with ```**argv[]``` the problem is not solved. Am I getting something wrong? – BillTheKid Dec 06 '21 at 10:21
  • @Jabberwocky, thank you! now I get it! this makes sense – BillTheKid Dec 06 '21 at 10:22

1 Answers1

2

get_command sets argv[0] and argv[1] to point to places within input. But, in the C model of computing, input ceases to exist when get_command returns, meaning the memory used for it is released and may be reused for other purposes.

Then the pointers in argv[0] and argv[1] become invalid, and the contents of the memory they pointed to may change, which likely happens when cd executes.

get_command should use malloc to allocate memory for the command or its parts. For good form, program should also free that memory when it is done using it.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Yes this answers my question! thank you! – BillTheKid Dec 06 '21 at 10:26
  • More correctly, it's the Algol60 model of computing ("Look, mama, I invented something! If I stack things likes so I can unstack them in reverse order without messing everything up!") ;-) [Friedrich L. Bauer](https://cacm.acm.org/blogs/blog-cacm/185577-the-life-of-a-computer-pioneer/fulltext) must have played with woodblocks as a child. – Peter - Reinstate Monica Dec 06 '21 at 10:39