Как найти местоположение исполняемого файла в C? [дубликат]
этот вопрос уже есть ответ здесь:
есть ли способ В C / C++ найти местоположение (полный путь) текущей выполняемой программы?
(проблема с argv[0]
Это то, что он не дает полного пути.)
9 ответов
подведем итоги:
-
на Униксах с
/proc
действительно прямой и реальный способ:readlink("/proc/self/exe", buf, bufsize)
(Linux)readlink("/proc/curproc/file", buf, bufsize)
(FreeBSD)readlink("/proc/self/path/a.out", buf, bufsize)
(Солярис)
-
на Униксах без
/proc
(т. е. если выше не получится):если argv[0] начинается с "/" (полный путь) это путь.
в противном случае, если argv[0] содержит " / " (относительный путь), добавьте его в cwd (предполагая, что он еще не был изменен).
в противном случае поиск в каталогах
$PATH
для исполняемого файлаargv[0]
.
после этого может быть разумно проверить, не является ли исполняемый файл на самом деле символической ссылкой. Если он разрешен относительно каталога symlink.
этот шаг не является необходимым в методе /proc (at крайней мере для Linux). Там символическая ссылка proc указывает непосредственно на исполняемый файл.
обратите внимание, что это до вызывающего процесса, чтобы установить
argv[0]
правильно. Это верно в большинстве случаев, однако есть случаи, когда вызывающему процессу нельзя доверять (ex. setuid исполняемый файл). в Windows: используйте
GetModuleFileName(NULL, buf, bufsize)
обратите внимание, что следующие комментарии только для unix.
педантичный ответ на этот вопрос заключается в том, что нет общие способ ответить на этот вопрос правильно во всех случаях. Как вы обнаружили, argv[0] может быть установлен на что угодно родительским процессом, и поэтому не должно иметь никакого отношения к фактическому имени программы или ее местоположению в файловой системе.
однако часто работает следующая эвристика:
- если argv[0] является абсолютным путем, предположим, что это полный путь к исполняемому файлу.
- если argv[0] является относительным путем, то есть содержит
/
, определите текущий рабочий каталог с помощью getcwd (), а затем добавьте к нему argv[0]. - если argv[0] - это простое слово, найдите $PATH, ища argv[0], и добавьте argv[0] в любой каталог, в котором вы его найдете.
заметьте что все из этих можно обойти процессом который вызван той или иной программы. Наконец, вы можете использовать методы, специфичные для linux, такие как EMG-2. Вероятно, есть эквивалентные методы в других операционных системах.
даже если предположить, что шаги выше дают вам действительное имя пути, у вас все равно может не быть имени пути, которое вы действительно хотите (так как я подозреваю, что вы действительно хотите найти файл конфигурации где-то). Наличие жестких ссылок означает, что вы можете иметь следующее ситуация:
-- 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
Теперь подход выше (включая, я подозреваю, /proc / $pid / exe) даст /some/where/else/foo
как реальный путь к программе. И, на самом деле, это a реальный путь к программе, только не тот, который вы хотели. Обратите внимание, что эта проблема не возникает с символическими ссылками, которые гораздо чаще встречаются на практике, чем жесткие ссылки.
несмотря на то, что этот подход в принципе ненадежен, он достаточно хорошо работает на практике для большинства цели.
не ответ на самом деле, а просто Примечание, чтобы иметь в виду.
как мы могли видеть, проблема поиска местоположения исполняемого файла довольно сложна и специфична для платформы в Linux и Unix. Нужно дважды подумать, прежде чем делать это.
Если вам нужно ваше исполняемое местоположение для обнаружения некоторых файлов конфигурации или ресурсов, возможно, вам следует следовать способу Unix размещения файлов в системе: put configs to /etc
или /usr/local/etc
или в текущем доме пользователя каталог, и /usr/share
- хорошее место для размещения файлов ресурсов.
во многих системах POSIX вы можете проверить simlink, расположенный под /proc/PID / exe. Несколько примеров:
# 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
помните, что в системах Unix двоичный файл может быть удален с момента его запуска. Это совершенно законно и безопасно в Unix. Насколько я знаю Windows не позволит вам удалить запущенный бинарник.
/proc/self / exe по-прежнему будет читаемым, но это не будет рабочая символическая ссылка на самом деле. Так и будет... странный.
для Linux вы можете найти /proc/self/exe
способ делать вещи, связанные в хорошей библиотеке под названием binreloc, вы можете найти библиотеку по адресу:
в Mac OS X Используйте _NSGetExecutablePath
.
посмотреть man 3 dyld
и ответ на подобный вопрос.
Я
1) Используйте функцию basename ():http://linux.die.net/man/3/basename
2) chdir () в этот каталог
3) Используйте getpwd (), чтобы получить текущий каталог
таким образом, вы получите каталог в аккуратной, полной форме, а не ./ или. ./закром./
возможно, вы захотите сохранить и восстановить текущий каталог, если это важно для вашей программы.