Does ISO C allow aliasing of the argv[] pointers supplied to main()?

  • A+

ISO C requires that hosted implementations call a function named main. If the program receives arguments, they are received as an array of char* pointers, the second argument in main's definition int main(int argc, char* argv[]).

ISO C also requires that the strings pointed to by the argv array be modifiable.

But can the elements of argv alias one another? In other words, can there exist i, j such that

  • 0 >= i && i < argc
  • 0 >= j && j < argc
  • i != j
  • argv[i] != NULL
  • argv[j] != NULL
  • 0 < strlen(argv[i])
  • strlen(argv[i]) <= strlen(argv[j])
  • argv[i] aliases argv[j]

at program start-up? If so, a write through argv[i][0] would also be seen through the aliasing string argv[j].

The relevant clauses of the ISO C Standard are below, but do not allow me to conclusively answer the titular question.

§ Program startup

The function called at program startup is named main. The implementation declares no prototype for this function. It shall be defined with a return type of int and with no parameters:

int main(void) { /* ... */ } 

or with two parameters (referred to here as argc and argv, though any names may be used, as they are local to the function in which they are declared):

int main(int argc, char *argv[]) { /* ... */ } 

or equivalent; 10) or in some other implementation-defined manner.

If they are declared, the parameters to the main function shall obey the following constraints:

  • The value of argc shall be nonnegative.
  • argv[argc] shall be a null pointer.
  • If the value of argc is greater than zero, the array members argv[0] through argv[argc-1] inclusive shall contain pointers to strings, which are given implementation-defined values by the host environment prior to program startup. The intent is to supply to the program information determined prior to program startup from elsewhere in the hosted environment. If the host environment is not capable of supplying strings with letters in both uppercase and lowercase, the implementation shall ensure that the strings are received in lowercase.
  • If the value of argc is greater than zero, the string pointed to by argv[0] represents the program name; argv[0][0] shall be the null character if the program name is not available from the host environment. If the value of argc is greater than one, the strings pointed to by argv[1] through argv[argc-1] represent the program parameters.
  • The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.

By my reading, the answer to the titular is "yes", since nowhere is it explicitly forbidden and nowhere does the standard urge or require the use of restrict-qualified argv, but the answer might turn on the interpretation of "and retain their last-stored values between program startup and program termination.".

The practical import of this question is that if the answer to it is indeed "yes", a portable program that wishes to modify the strings in argv must first perform (the equivalent of) POSIX strdup() on them for safety.


The way it works on common *nix platforms (including Linux and Mac OS, presumably FreeBSD too) is that argv is an array of pointers into a single memory area containing the argument strings one after another (separated only by the null terminator). Using execl() does not change this--even if the caller passes the same pointer multiple times, the source string is copied multiple times, with no special behavior for identical (i.e. aliased) pointers (an uncommon case with no great benefit to optimize).

However, C does not require this implementation. The truly paranoid may want to copy every string before modifying it, perhaps skipping the copies if memory is limited and a loop over argv shows that none of the pointers actually alias (at least among those the program intends to modify). This seems overly paranoid unless you are developing flight software or the like.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: