Как найти расположение исполняемого файла в C? [дубликат]
этот вопрос уже есть ответ здесь:
- Поиск пути текущего исполняемого файла без /proc / self / exe 12 ответов
есть ли способ в 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)
(Солярис)на Unixes без
/proc
(т. е. если выше не получится):
если argv[0] начинается с "/" (полный путь) это путь.
в противном случае, если argv[0] содержит "/" (относительный путь), добавьте его в cwd (предполагая, что он еще не был изменен).
в противном случае поиск в каталогах
$PATH
для исполняемого файлаargv[0]
.после этого может быть разумно проверить, не является ли исполняемый файл на самом деле символической ссылкой. Если это разрешить его относительно каталога символической ссылки.
этот шаг не требуется в методе /proc (at крайней мере для Linux). Там символическая ссылка proc указывает непосредственно на исполняемый файл.
обратите внимание, что это до вызывающего процесса, чтобы установить
argv[0]
правильно. Это верно в большинстве случаев, однако есть случаи, когда вызывающий процесс не может быть доверенным (ex. дополнительное исполняемый).в Windows: используйте
GetModuleFileName(NULL, buf, bufsize)
использовать GetModuleFileName()
обратите внимание, что следующие комментарии только для 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 (), чтобы получить текущий каталогтаким образом, вы получите каталог в аккуратной, полной форме, а не ./ или. ./закром./
возможно, вы захотите сохранить и восстановить текущий каталог, если это важно для вашей программы.