2008-12-21 9 views
8

Ésta es una cuestión fundamental, pero una muy importante, no obstante ...¿Está garantizado que args [0] sea la ruta de ejecución?

Al iniciar un programa en C++ cuyo principal método tiene la siguiente firma común:

int main(int argc, char* args[]) { 
    //Magic! 
    return 0; 
} 

es args [0 ] ¿Siempre se garantiza que será la ruta al programa actualmente en ejecución? ¿Qué pasa con la plataforma cruzada (dado que estoy en un entorno Linux pero puedo realizar el puerto más adelante)?

Respuesta

21

No siempre es así. Es el valor que le dio al programa por el sistema de operación. Por ejemplo al iniciar un programa utilizando exec puede establecer que a un valor arbitrario:

int execve(const char *filename, char *const argv[], 
      char *const envp[]); 

El primer parámetro es el archivo para iniciar, y la voluntad argv contiene argv [0] y todos los demás parámetros para las principales. envp contiene las variables de entorno (no definidas por Standard C o C++. Esto es una cosa posix).

Más precisamente, esta es la definición de argv en C++:

Una implementación no se predefinir la función principal. Esta función no debe estar sobrecargada. Deberá tener un tipo de retorno de tipo int, pero de lo contrario su tipo está definido por la implementación. Todas las implementaciones se permiten ambas de las siguientes definiciones de principal:

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

y

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

En la forma última argc será el número de argumentos pasados ​​a la programa del entorno en que ejecuta el programa. Si argc es distinto de cero estos argumentos se proporcionarán en argv[0] través argv[argc-1] como punteros a los caracteres iniciales de las cadenas terminadas en cero de varios bytes (NTMBSs) (17.3.2.1.3.2) y argv[0] será el puntero al carácter inicial de un NTMBS que representa el nombre utilizado para invocar el programa o "". El valor de argc debe ser no negativo. El valor de argv[argc] será 0. [Nota: se recomienda agregar cualquier parámetro adicional (opcional) después de argv. ]

Depende mucho de la implementación lo que define un "nombre usado para invocar el programa". Si desea obtener la ruta completa de su ejecutable, puede usar GetModuleFileName en Windows, y argv[0] (para obtener el nombre utilizado para ejecutar, puede ser relativo) junto con getcwd (para obtener el directorio de trabajo actual, tratando de hacer que el nombre absoluto).

+0

Por ejemplo, un shell sabe que es un shell de inicio de sesión porque el inicio de sesión (1) hace que argv [0] comience con un guion. –

+0

... y bash sabe que está en modo POSIX comparando argv [0] con "sh" :) por cierto, este truco de argv es lo que hace que busybox sea tan pequeño. todos los utils se empaquetan juntos en un binario que se acaba de ejecutar con diferentes valores de argv [0] –

+0

Evitaré el realpath en los programas portátiles. La interfaz POSIX realpath está rota, porque no puede especificar el tamaño del búfer de destino, ni asignar uno lo suficientemente grande sin hacer suposiciones sobre PATH_MAX. – Doug

2

Esto es lo que el estándar de C dice que argv[0] debería ser:

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 es disponible desde el entorno de host.

En cuanto a si contiene la ruta completa, la respuesta es que argv [0] no contiene necesariamente la ruta completa al ejecutable. En Windows, parece ser exactamente lo que se proporcionó en la línea de comando. No sé qué hace Linux/Unix.

5

No. En Windows GetModuleFileName garantiza la ruta completa exacta al programa de ejecución actual. En Linux hay un enlace simbólico/proc/self/exe. Haga un readlink en este enlace simbólico para obtener la ruta completa del programa en ejecución. Incluso si su programa fue llamado por un enlace simbólico/proc/auto/exe siempre apuntará al programa real.

3

No está tan garantizado que los estudiantes solían ocultar el hecho de que estaban jugando Rogue en el mainframe de la escuela escribiendo programas C que comenzarían con argv [0] de "cc" o "tcsh".

+1

Con las versiones antiguas de 'ps' y 'w' incluso funcionó. :) – chaos

Cuestiones relacionadas