Pregunta ¿Es argv [n] escribible?


C11 5.1.2.2.1 / 2 dice:

Los parametros argc y argv y las cuerdas apuntadas por el argv matriz deberá   ser modificable por el programa, y ​​retener sus últimos valores almacenados entre programa   inicio y finalización del programa.

Mi interpretación de esto es que especifica:

int main(int argc, char **argv)
{
    if ( argv[0][0] )
        argv[0][0] = 'x';   // OK

    char *q;
    argv = &q;              // OK
}

sin embargo, no dice nada sobre:

int main(int argc, char **argv)
{
    char buf[20];
    argv[0] = buf;
}

Es argv[0] = buf; ¿permitido?

Puedo ver (al menos) dos posibles argumentos:

  • La cita anterior mencionada deliberadamente argv y argv[x][y] pero no argv[x], entonces la intención era que no es modificable
  • argv es un puntero a noconst objetos, por lo que, en ausencia de una redacción específica en contrario, debemos suponer que son objetos modificables.

32
2017-09-09 05:48


origen


Respuestas:


IMO, código como argv[1] = "123"; es UB.


"Los parámetros argc y argv y las cadenas señaladas por la matriz argv deberán   ser modificable por el programa, y ​​retener sus últimos valores almacenados entre programa   puesta en marcha y finalización del programa. "C11dr §5.1.2.2.1 2

Recordar que const entró en C muchos años después de la creación de C.

Muy parecido char *s = "abc"; es válido cuando debería ser const char *s = "abc";. La necesidad de const no se requería demasiado, el código existente se habría roto con la introducción de const.

Del mismo modo, incluso si argv hoy debe ser considerado char * const argv[] o alguna otra firma con const, la falta de const en el char *argv[] no completa, especifique el const-las necesidades de la argv, argv[], o argv[][]. los constlas necesidades de la identidad deberían ser impulsadas por la especificación.

Desde mi lectura, ya que la especificación no dice nada sobre el tema, es UB.

El comportamiento indefinido está indicado de otra manera en esta Norma Internacional por las palabras "comportamiento indefinido" o por el omisión de cualquier definición explícita de comportamiento"§4 2


[editar]:

main() es una función muy especial es C. Lo que está permitido en otras funciones puede o no estar permitido en main(). La especificación C detalla los atributos sobre sus parámetros que dieron la firma int argc, char *argv[] eso no debería necesitar main(), a diferencia de otras funciones en C, puede tener una firma alternativa int main(void) y potencialmente otros. main() no es reentrante A medida que la especificación C se desvía de su camino para detallar lo que se puede modificar: argc, argv, argv[][], es razonable preguntar si argv[] es modificable debido a su omisión de la especificación que afirma que el código puede.

Dada la especialidad de main() y la omisión de especificar que argv[] como modificable, un programador conservador trataría esta grisura como UB, pendiente de aclaración futura de especificaciones C.


Si argv[i] es modificable en una plataforma determinada, sin duda el rango de i No debe excederse argc-1.

Como "argv[argc] será un puntero nulo ", asignando argv[argc] a algo más que NULL parece ser una violación

Aunque las cadenas son modificables, el código no debe exceder la longitud original de la cadena.

char *newstr = "abc";
if (strlen(newstr) <= strlen(argv[1])) 
  strcpy(argv[1], newstr);

6
2017-09-09 14:43



argc es solo una inty es modificable sin ninguna restricción.

argv es un cambio modificable char **. Esto significa que argv[i] = x es válida. Pero no dice nada sobre argv[i] siendo él mismo modificable. Asi que argv[i][j] = c conduce a un comportamiento indefinido

los getopt la función de la biblioteca estándar C modifica argc y argv, pero nunca modifica las matrices char reales.


0
2017-09-09 15:46



Se menciona claramente que argv y argv[x][x] es modificable Si argv es modificable, entonces puede apuntar a otro primer elemento de una matriz de char y por lo tanto argv[x] puede señalar el primer elemento de alguna otra cadena. Por último argv[x] es modificable también y esa podría ser la razón por la cual no hay necesidad de mencionarlo explícitamente en el estándar.


-1
2017-09-09 06:10



La respuesta es que argv es una matriz y sí, su contenido es modificable.

La clave es anterior en la misma sección:

Si el valor de argc es mayor que cero, el formación miembros argv [0] a través de   argv [argc-1] inclusive debe contener punteros a las cadenas, que se dan   valores definidos por la implementación por el entorno de host antes del inicio del programa.

A partir de esto, está claro que argv debe considerarse como una matriz de una longitud específica (argc). Entonces * argv es un puntero a esa matriz, habiendo decaído a un puntero.

Leído en este contexto, la afirmación de que 'argv debe ser modificable ... y conservar sus contenidos' claramente tiene la intención de que los contenidos de esa matriz sean modificables.

Admito que sigue habiendo cierta ambigüedad en la redacción, particularmente en lo que podría suceder si se modifica argc.


Para que quede claro, lo que estoy diciendo es que leo este lenguaje como un significado:

[el contenido de] argv [matriz] y las cadenas apuntadas por la matriz argv serán modificables ...

Entonces, tanto los punteros en el arreglo como las cadenas a las que apuntan están en la memoria de lectura-escritura, no se hace daño al cambiarlos, y ambos preservan sus valores durante la vida del programa. Esperaría que este comportamiento se encuentre en todas las principales implementaciones de la biblioteca en tiempo de ejecución C / C ++, sin excepción. Esto no es UB.

La ambigüedad es la mención de argc. Es difícil imaginar cualquier propósito o implementación en la que el valor de argc (que parece ser simplemente un parámetro de función local) no pueda cambiarse, entonces ¿por qué mencionarlo? La norma establece claramente que una función puede cambiar el valor de sus parámetros, entonces ¿por qué tratar a argc especialmente a este respecto? Es esta mención inesperada de argc lo que ha desencadenado esta preocupación sobre argv, que de otro modo pasaría sin comentario. Elimina argc de la oración y la ambigüedad desaparece.


-1
2017-09-11 13:59