c++ - compilar - gcc compilador
¿Cómo encuentro la ubicación del ejecutable en C? (9)
En Mac OS X, use _NSGetExecutablePath
.
Ver _NSGetExecutablePath y esta respuesta a una pregunta similar.
Esta pregunta ya tiene una respuesta aquí:
¿Hay alguna forma en C / C ++ para encontrar la ubicación (ruta completa) del programa ejecutado actualmente?
(El problema con argv[0]
es que no proporciona la ruta completa).
En muchos sistemas POSIX puede verificar un enlace ubicado en / proc / PID / exe. Algunos ejemplos:
# file /proc/*/exe
/proc/1001/exe: symbolic link to /usr/bin/distccd
/proc/1023/exe: symbolic link to /usr/sbin/sendmail.sendmail
/proc/1043/exe: symbolic link to /usr/sbin/crond
No es una respuesta en realidad, sino solo una nota para tener en cuenta.
Como pudimos ver, el problema de encontrar la ubicación del ejecutable en ejecución es bastante complicado y específico de la plataforma en Linux y Unix. Uno debería pensar dos veces antes de hacer eso.
Si necesita su ubicación ejecutable para descubrir algunos archivos de configuración o recursos, tal vez deba seguir la forma Unix de colocar archivos en el sistema: ponga las configuraciones en /etc
o /usr/local/etc
o en el directorio de inicio del usuario actual, y /usr/share
es un buen lugar para poner sus archivos de recursos.
Para Linux puede encontrar la forma /proc/self/exe
de hacer las cosas agrupadas en una bonita biblioteca llamada binreloc, puede encontrar la biblioteca en:
Para resumir:
En Unixes con
/proc
realmente recta y realiable es:readlink("/proc/self/exe", buf, bufsize)
(Linux)readlink("/proc/curproc/file", buf, bufsize)
(FreeBSD)readlink("/proc/self/path/a.out", buf, bufsize)
(Solaris)
En Unixes sin
/proc
(es decir, si lo anterior falla):Si argv [0] comienza con "/" (ruta absoluta) esta es la ruta.
De lo contrario, si argv [0] contiene "/" (ruta relativa), agréguela a cwd (suponiendo que todavía no se haya cambiado).
De lo contrario, buscar directorios en
$PATH
para el archivo ejecutableargv[0]
.
Después, puede ser razonable comprobar si el ejecutable no es en realidad un enlace simbólico. Si es resolverlo en relación con el directorio de enlace simbólico.
Este paso no es necesario en el método / proc (al menos para Linux). Allí, el enlace simbólico proc apunta directamente al ejecutable.
Tenga en cuenta que corresponde al proceso de llamada establecer
argv[0]
correctamente. Es correcto la mayoría de las veces, sin embargo, hay ocasiones en que no se puede confiar en el proceso de llamada (por ejemplo, ejecutable de setuid).En Windows: use
GetModuleFileName(NULL, buf, bufsize)
Recuerde que en los sistemas Unix el binario puede haberse eliminado desde que se inició. Es perfectamente legal y seguro en Unix. La última vez que verifiqué, Windows no le permitirá eliminar un binario en ejecución.
/ proc / self / exe seguirá siendo legible, pero realmente no será un enlace simbólico activo. Será ... extraño.
Tenga en cuenta que los siguientes comentarios son solo de Unix.
La respuesta pedante a esta pregunta es que no hay una manera general de responder esta pregunta correctamente en todos los casos. Como ha descubierto, argv [0] se puede establecer en todo por el proceso principal, por lo que no debe tener relación alguna con el nombre real del programa o su ubicación en el sistema de archivos.
Sin embargo, la siguiente heurística a menudo funciona:
- Si argv [0] es una ruta absoluta, supongamos que esta es la ruta completa al ejecutable.
- Si argv [0] es una ruta relativa, es decir, contiene un
/
, determine el directorio de trabajo actual con getcwd () y luego agregue argv [0] a él. - Si argv [0] es una palabra simple, busque $ PATH buscando argv [0] y añada argv [0] al directorio en el que lo encuentre.
Tenga en cuenta que todos estos pueden ser evitados por el proceso que invoca el programa en cuestión. Finalmente, puede usar técnicas específicas de Linux, como las mencionadas por emg-2. Probablemente haya técnicas equivalentes en otros sistemas operativos.
Incluso suponiendo que los pasos anteriores le den un nombre de ruta válido, puede que aún no tenga el nombre de ruta que realmente desea (ya que sospecho que lo que realmente desea hacer es encontrar un archivo de configuración en alguna parte). La presencia de enlaces duros significa que puede tener la siguiente situación:
-- assume /app/bin/foo is the actual program
$ mkdir /some/where/else
$ ln /app/bin/foo /some/where/else/foo # create a hard link to foo
$ /some/where/else/foo
Ahora, el enfoque anterior (incluyendo, sospecho, / proc / $ pid / exe) dará /some/where/else/foo
como la ruta real al programa. Y, de hecho, es un camino real hacia el programa, simplemente no el que usted quería. Tenga en cuenta que este problema no ocurre con enlaces simbólicos que son mucho más comunes en la práctica que los enlaces duros.
A pesar del hecho de que este enfoque es, en principio, poco confiable, funciona bastante bien en la práctica para la mayoría de los propósitos.
Use la GetModuleFileName() si está usando Windows.
me gustaría
1) Use la función basename (): http://linux.die.net/man/3/basename
2) chdir () a ese directorio
3) Use getpwd () para obtener el directorio actual
De esta forma obtendrá el directorio en una forma ordenada y completa, en lugar de ./ o ../bin/.
Tal vez desee guardar y restaurar el directorio actual, si eso es importante para su programa.