143 votes

Comment trouver l'emplacement de l'exécutable en C ?

Existe-t-il un moyen en C/C++ de trouver l'emplacement (chemin complet) du programme en cours d'exécution ?

(Le problème avec argv[0] est qu'il ne donne pas le chemin complet).

192voto

lispmachine Points 2379

Pour résumer :

  • Sur les Unix avec /proc Le moyen le plus direct et le plus réaliste est de :

    • readlink("/proc/self/exe", buf, bufsize) (Linux)

    • readlink("/proc/curproc/file", buf, bufsize) (FreeBSD)

    • readlink("/proc/self/path/a.out", buf, bufsize) (Solaris)

  • Sur les Unix sans /proc (c'est-à-dire en cas d'échec de ce qui précède) :

    • Si argv[0] commence par "/" (chemin absolu) c'est le chemin.

    • Sinon, si argv[0] contient "/" (chemin relatif), il est ajouté à cwd (en supposant qu'il n'a pas encore été modifié).

    • Sinon, recherchez les répertoires dans $PATH pour l'exécutable argv[0] .

    Ensuite, il peut être raisonnable de vérifier si l'exécutable n'est pas en fait un lien symbolique. S'il l'est, résolvez-le relativement au répertoire du lien symbolique.

    Cette étape n'est pas nécessaire dans la méthode /proc (du moins pour Linux). Là, le lien symbolique proc pointe directement vers l'exécutable.

    Notez que c'est au processus appelant de définir argv[0] correctement. Il est correct la plupart du temps, mais il y a des occasions où le processus appelant ne peut pas être fiable (ex. exécutable setuid).

  • Sous Windows : utilisez GetModuleFileName(NULL, buf, bufsize)

22voto

Shino C G Points 661

Utilice GetModuleFileName() si vous utilisez Windows.

17voto

Dale Hagglund Points 7159

Veuillez noter que les commentaires suivants sont réservés à unix.

La réponse pédante à cette question est qu'il n'y a pas généralités moyen de répondre correctement à cette question dans tous les cas. Comme vous l'avez découvert, argv[0] peut être défini comme n'importe quoi par le processus parent, et n'a donc aucune relation avec le nom réel du programme ou son emplacement dans le système de fichiers.

Cependant, l'heuristique suivante fonctionne souvent :

  1. Si argv[0] est un chemin absolu, supposez que c'est le chemin complet de l'exécutable.
  2. Si argv[0] est un chemin relatif, c'est-à-dire qu'il contient un / détermine le répertoire de travail actuel avec getcwd() et y ajoute ensuite argv[0].
  3. Si argv[0] est un mot simple, recherchez argv[0] dans $PATH, et ajoutez argv[0] au répertoire dans lequel vous le trouvez.

Notez que toutes ces mesures peuvent être contournées par le processus qui a invoqué le programme en question. Enfin, vous pouvez utiliser des techniques spécifiques à linux, comme celles mentionnées par emg-2. Il existe probablement des techniques équivalentes sur d'autres systèmes d'exploitation.

Même en supposant que les étapes ci-dessus vous donnent un nom de chemin valide, il se peut que vous n'ayez pas le nom de chemin que vous voulez réellement (puisque je soupçonne que ce que vous voulez réellement faire est trouver un fichier de configuration quelque part). La présence de liens durs signifie que vous pouvez vous retrouver dans la situation suivante :

-- 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

Maintenant, l'approche ci-dessus (y compris, je suppose, /proc/$pid/exe) donnera /some/where/else/foo comme le véritable chemin vers le programme. Et, en fait, c'est a le vrai chemin vers le programme, mais pas celui que vous vouliez. Notez que ce problème ne se produit pas avec les liens symboliques qui sont beaucoup plus courants en pratique que les liens durs.

Bien que cette approche soit en principe peu fiable, elle fonctionne suffisamment bien dans la pratique pour la plupart des cas.

10voto

Michael Points 387

Ce n'est pas une réponse en fait, mais juste une note à garder à l'esprit.

Comme nous avons pu le constater, le problème de la recherche de l'emplacement de l'exécutable en cours d'exécution est assez délicat et spécifique à la plateforme sous Linux et Unix. Il faut y réfléchir à deux fois avant de le faire.

Si vous avez besoin de l'emplacement de votre exécutable pour découvrir certains fichiers de configuration ou de ressources, vous devriez peut-être suivre la méthode Unix de placement des fichiers dans le système : mettez les configs dans le répertoire /etc ou /usr/local/etc ou dans le répertoire personnel de l'utilisateur actuel, et /usr/share est un bon endroit pour mettre vos fichiers de ressources.

6voto

Dans de nombreux systèmes POSIX, vous pouviez vérifier un simlink situé sous /proc/PID/exe. Quelques exemples :

# 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X