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

cette question a déjà une réponse ici:

y a-t-il un moyen en C/C++ de trouver l'emplacement (chemin complet) du programme courant exécuté?

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

135
demandé sur Peter Mortensen 2009-06-01 11:29:47

9 réponses

pour résumer:

  • Sur Unix avec /proc vraiment simple et fiable moyen 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 Unixes sans /proc (c'est à dire si au-dessus échoue):

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

    • dans les autres cas, si argv[0] contient "/" (trajectoire relative), l'ajouter à cwd (en supposant qu'elle n'ait pas encore été changée).

    • autrement rechercher des 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 réellement un lien symbolique. S'il est résolu par rapport au répertoire symlink.

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

    notez qu'il appartient au processus d'appel de définir argv[0] correctement. Il est juste la plupart du temps, mais il ya des occasions où le processus d'appel ne peut pas être de confiance (ex. setuid exécutable).

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

182
répondu lispmachine 2011-05-24 18:56:30

Utiliser GetModuleFileName() fonction si vous utilisez Windows.

18
répondu Shino C G 2009-06-01 07:43:33

veuillez noter que les commentaires suivants sont unix-seulement.

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

cependant, les heuristiques suivantes souvent œuvres:

  1. si argv[0] est un chemin absolu, supposons 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éterminez le répertoire de travail courant avec getcwd() et ajoutez argv[0] à celui-ci.
  3. si argv[0] est un mot simple, Cherchez $PATH à la recherche d'argv[0], et ajoutez argv[0] à n'importe quel répertoire où vous le trouverez.

Notez que tous ces éléments 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, vous pourriez ne pas avoir le nom de chemin que vous voulez réellement (puisque je soupçonne que ce que vous voulez réellement faire est de trouver un fichier de configuration quelque part). Présence de liens durs signifie que vous pouvez avoir 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 (incluant, je soupçonne, /proc/$pid/exe) donnera /some/where/else/foo comme véritable chemin vers le programme. Et, en fait, c'est un vrai chemin d'accès au programme, mais pas celui que vous vouliez. Notez que ce problème ne se produit pas avec les liens symboliques qui sont beaucoup plus communs dans la pratique que les liens durs.

malgré le fait que cette approche est en principe peu fiable, elle fonctionne assez bien dans la pratique pour la plupart des cas.

15
répondu Dale Hagglund 2009-06-01 08:45:04

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

comme nous avons pu le voir, le problème de trouver l'emplacement de l'exécutable en cours d'exécution est assez délicat et spécifique à la plate-forme sous Linux et Unix. On devrait y réfléchir à deux fois avant de faire ça.

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

9
répondu Michael 2009-06-02 11:34:22

dans de nombreux systèmes POSIX, vous pouvez 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
6
répondu MestreLion 2014-07-15 08:19:16

se rappeler que sur les systèmes Unix le binaire peut avoir été enlevé depuis qu'il a été commencé. C'est parfaitement légal et sécurisé sur Unix. Dernière, j'ai vérifié Windows ne vous permettra pas de supprimer l'exécution d'un binaire.

/proc/self / exe sera toujours lisible, mais ce ne sera pas vraiment un lien symbolique fonctionnel. Il sera... bizarre.

4
répondu Thomas 2016-10-16 09:05:50

Pour Linux vous pouvez trouver la /proc/self/exe façon de faire les choses emmitouflé dans une belle bibliothèque appelée binreloc, vous pouvez trouver la bibliothèque à:

3
répondu Grumbel 2009-08-05 21:40:54

sur Mac OS X, utiliser _NSGetExecutablePath .

voir man 3 dyld et cette réponse à une question similaire.

3
répondu Tim Ruddick 2017-05-23 11:47:23

je

1) utiliser la fonction basename (): http://linux.die.net/man/3/basename

2) chdir() vers le répertoire

3) Utilisez getpwd () pour obtenir le répertoire courant

de cette façon, vous obtiendrez le répertoire dans une forme soignée, complète, au lieu de ./ ou. ./bac./

peut-être que vous voudrez sauvegarder et restaurer le répertoire courant, si cela est important pour votre programme.

0
répondu JCCyC 2009-06-19 19:03:20