Pregunta

Encontré dos formas de pasar argumentos de línea de comandos a una matriz de caracteres:

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);
}

Compilado con el compilador IBM xlc en un sistema AIX Devuelve

  

[MyPrompt] > ./a.out

     

s1: ./a.out

     

s2: ./a.out

¿Qué implementación (s1 o s2) es correcta? s1 es bueno porque argv [0] puede tener cualquier longitud. s2 requiere que la longitud de argv [0] < 256 caracteres.

No entiendo cómo / por qué s1 debería funcionar. Creo que creo el lado derecho de s1 debería ser necesario en el momento de la compilación, pero creo que se genera en tiempo de ejecución.

¿Fue útil?

Solución

La razón por la que s1 funciona es porque el tipo de argv [0] es un puntero. Simplemente está asignando la dirección (no el valor real), que es segura. No estás realizando ningún tipo de asignación o reparto.

Normalmente prefiero la primera opción, ya que solo debería leer las variables de argumento.

Otros consejos

Si no desea cambiar la cadena, entonces s1 funcionará.

Si desea cambiar la cadena, puede hacer una copia de ella. Sin embargo, debe usar strnlen () y strncpy () más seguros si su sistema lo admite.

  

Creo que el lado derecho de s1   debe ser requerido en tiempo de compilación,   pero creo que se genera en   tiempo de ejecución.

No, se requiere cada vez que se encuentra la declaración. Por ejemplo:

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

El entero x se inicializará a 1 cada vez que se llame a la función, no en tiempo de compilación.

s2 tiene la encantadora propiedad de ser susceptible a un desbordamiento del búfer.

He visto a personas cambiar el valor de argv [0]. En algunos casos, (en algunos sistemas operativos) cambiar argv [0] hará que el programa se muestre en ps como lo haya cambiado.

Si solo desea hacer referencia al argumento sin realizar ningún cambio, entonces s1 es correcto.

Si necesita modificar el argumento de alguna manera, debe hacer una copia del mismo como en el ejemplo s2 , pero en el ejemplo s2 debe verificar explícitamente vea si la longitud es mayor que el búfer al que lo está copiando. Por ejemplo, si está tomando un argumento como filename.jpg como entrada y guardando filename.gif como salida, entonces necesita hacer una copia de ese argumento ya que cambiará la extensión de .jpg a .gif

Iría con s1, especialmente para argv [n] donde n > 0. Cosas como s2 te abren para ataques clásicos de desbordamiento de búfer. Básicamente, un usuario puede formatear un argumento que tiene más de 256 caracteres de longitud y sobrescribir la información en la pila para que pueda ejecutar el código que desee.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top