2011-12-29 27 views
8

En cualquier programa C, el argumento de línea de comando argv[0] apunta al nombre utilizado para invocar el programa. ¿Hay alguna circunstancia en la que apunte a una cadena vacía ""?¿Puede argv [0] contener una cadena vacía?

Un ejemplo de fragmento de código para un caso así sería una buena referencia.

+1

¿Por qué no diseñar su programa para que funcione independientemente? O use una afirmación de tiempo de ejecución. – tangrs

+1

Mejor llamarlo una cadena vacía; cadena nula se puede confundir fácilmente con un puntero nulo. –

+0

@JonathanLeffler: Editado –

Respuesta

9

Su implementación está definida. §5.1.2.2.1 abreviado:

  • Si el valor de argc es mayor que cero, los miembros de la matriz a través de argv[0] argv[argc-1] inclusive deberá contener punteros a cadenas, que se dan valores definido por la implementación por el entorno de host antes del inicio del programa. El intento de es proporcionar a la información del programa determinada antes del inicio del programa desde otro lugar en el entorno alojado. [...]

  • Si el valor de argc es mayor que cero, la cadena apuntada por argv[0] representa el nombre del programa; argv[0][0] será el carácter nulo si el nombre del programa no está disponible desde el entorno host. [...]

Así que si argc es mayor que cero, es bastante la intención que argv[0] no ser una cadena vacía, pero podría suceder. (Tenga en cuenta que con argc igual a n, argv[0] través argv[n - 1] nunca son nulos y siempre apuntan a una cadena. La cadena en sí puede estar vacío, sin embargo. Si n es cero, argv[0] es nulo.)

En la práctica, por supuesto , solo necesitas asegurarte de que las plataformas en las que te diriges se comporten según sea necesario.

+0

De hecho, si 'argv [0] [0]' puede ser 0 'argv [0]' puede 'estar' vacío. – alk

+0

@alk: 'argv [0]' nunca es nulo cuando 'argc' es mayor que cero, pero puede apuntar a una cadena vacía. – GManNickG

+0

@KeithThompson: lo que sea ... ;-) – alk

1

argv [0] puede ser nulo en C, por ejemplo, si usted invoca directamente una función principal (con algunos trucos se puede hacer en C). No sé si C++ permite la invocación principal directa.

+0

¿Puedes mostrarnos tales trucos? –

+0

¿No está el OP preguntando por 'argv [0]' refiriéndose a una cadena vacía ('" "', '{'\ 0'}'), pero a 'argv [0]' siendo 'NULL'? – alk

+0

@alk El OP es sobre cadena vacía/nula y no 'argv [0] = NULL' –

6

Sí.

El estándar del lenguaje C permite explícitamente la posibilidad de que argv[0] puede ser un puntero nulo, o que puede apuntar a una cadena vacía (""). N1256 5.1.2.2.1p2:

El valor de argc será negativo.

argv [argc] será un puntero nulo.

[...]

Si el valor de argc es mayor que cero, la cadena apuntada por argv [0] representa el nombre del programa ; argv [0] [0] será el carácter nulo si el nombre del programa no está disponible desde el entorno host . Si el valor de argc es mayor que uno, las cuerdas apuntado por argv [1] través argv [argc-1] representan los parámetros del programa .

En los sistemas Unix, los programas son invocados por uno de los exec() familia de funciones (execl(), execlp(), etc.), que permiten que la persona que llama para especificar exactamente qué argumentos se pasan a la función main(). (Es incluso posible invocar un programa en formas que violan los requisitos impuestos por la norma C.)

Tenga en cuenta que la norma dice que argv[0] (asumiendo que es nula ni está vacía) "representa el nombre del programa". El estándar es deliberadamente vago sobre cómo representa el nombre del programa. En particular, no necesita proporcionar un nombre por el cual se pueda invocar el programa (ya que el estándar ni siquiera requiere que los programas puedan invocarse por nombre).

+1

No puede ser nulo, solo vacío. El párrafo anterior requiere que cada 'argv' señale una cadena (y que la última sea nula). Una implementación desagradable podría proporcionarles cadenas vacías, pero no todas. – GManNickG

+0

Si 'argc == 0', entonces' argv [0] 'es un puntero nulo. (No había citado esa parte cuando escribiste tu comentario.) –

+0

@GMan: Si ese fue tu voto negativo, reconsidera. –

5

Otras respuestas han citado el estándar C y muestran que argv[0] y pueden ser NULL o pueden ser la cadena vacía (""). Debe escribir su programa con la suposición de que esto puede suceder, porque de lo contrario está creando un (pequeño) riesgo de seguridad. Es fácil invocar su programa y establecer argv a cualquier cosa que desee un atacante. Como prueba, considere los siguientes dos programas. La primera de ellas, echoargv.c imprime el contenido de argv:

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) { 
    int i; 
    for (i = 0; i < argc; ++i) 
     printf("argv[%d] = \"%s\"\n", i, argv[i]); 
    exit(0); 
} 

El segundo, argv0, invoca a cualquier otro programa y permite al usuario especificar la otra argv del programa:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

int main(int argc, char **argv) { 
    (void) execv(argv[1], argv+2); 
    perror("execv"); 
    exit(1); 
} 

(Esta es una .-ambientes POSIX específica versión no estándar pueden necesitar cambios)

Aquí es cómo usarlos:.

$ gcc -o echoargv echoargv.c 
$ gcc -o argv0 argv0.c 
$ ./argv0 ./echoargv 
$ ./argv0 ./echoargv '' 
argv[0] = "" 
$ ./argv0 ./echoargv 'this is fun' 'it is fun indeed' 
argv[0] = "this is fun" 
argv[1] = "it is fun indeed" 
$ 

La primera ejecución de argv0 establece que echoargv's argv[0] es NULO. La segunda ejecución hace que sea la cadena vacía. La tercera ejecución es simplemente por diversión: tenga en cuenta que argv[0] no necesita tener nada que ver con el nombre real del programa.

¿Cómo te puede morder?Si, por ejemplo, que a ciegas imprimir el nombre de su programa en un mensaje de uso:

printf("usage: %s [options] [FILE]...\n", argv[0]); 

Mejor:

const char *program_name = "some default name"; /* (global) variable */ 
if (argv[0] && argv[0][0]) 
    program_name = argv[0]; 
printf("usage: %s [options] [FILE]...\n", program_name); 

Si no hace esto, un atacante puede hacer que su programa para segfault a voluntad, o puede hacer que su programa informe cosas completamente incorrectas al usuario.

+0

+1 para el impresionante ejemplo! ¡De hecho fue muy divertido leer tu publicación! Gracias :) –

Cuestiones relacionadas