Question

I found two ways of passing command-line arguments into a character array:

int main (int argc, char **argv)
{
  const char *s1 = argv[0];
  char s2[256];
  strcpy(s2, argv[0]);

  printf("s1: %s\ns2: %s\n\n", s1, s2);
}

Compiled with the IBM xlc compiler on an AIX system Returns

[MyPrompt]> ./a.out

s1: ./a.out

s2: ./a.out

Which implementation (s1 or s2) is correct? s1 is nice because argv[0] can be any length. s2 requires that the length of argv[0] < 256 characters.

I do not understand how/why s1 should work. I think the right-hand side of s1 should be required at compile time, but I think it's generated at run-time.

Was it helpful?

Solution

The reason s1 works is because the type of argv[0] is a pointer. You are simply assigning the address (not the actual value), which is safe. You aren't performing any kind of allocation or cast.

I typically prefer the first option as you should only be reading from the argument variables.

OTHER TIPS

If you don't want to change the string then s1 will work.

If you want change the string then you can make a copy of it. You should use the safer strnlen() and strncpy() though if your system supports it.

I think the right-hand side of s1 should be required at compile time, but I think it's generated at run-time.

No, it's required every time the statement is encountered. For example:

void f() {
   int x = 1;
   ...
}

The integer x will be initialised to 1 every time the function is called, not at compile time.

s2 has the delightful property of being susceptible to a buffer overrun.

I have seen people change the value of argv[0]. In some cases, (on some OSes) changing argv[0] will make the program show up in ps as whatever you changed it to.

If you just want to reference the argument without making any changes to it then s1 is correct.

If you need to modify the argument in any way then you need to make a copy of it like in the s2 example, but in the s2 example you need to explicitly check to see if the length is longer than the buffer you are copying it to. For example if you are taking an argument like filename.jpg as input and saving out filename.gif as the output then you need to make a copy of that argument since you will be changing the extension from .jpg to .gif

I would go with s1, especially for argv[n] where n > 0. Things like s2 open you up for classic buffer overflow attacks. Basically, a user can format an argument that's over 256 characters in length and overwrite information on the stack so they can run any code they want.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top