如何在C中找到可执行文件的位置?

时间:2009-06-01 07:29:47

标签: c++ c linux unix path

在C / C ++中是否有办法找到当前执行程序的位置(完整路径)?

argv[0]的问题在于它没有提供完整路径。)

9 个答案:

答案 0 :(得分:185)

总结:

  • 在具有/proc的Unix上,真正直接且可行的方法是:

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

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

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

  • 在没有/proc的Unix上(即如果失败):

    • 如果argv [0]以“/”(绝对路径)开头,则为路径。

    • 否则,如果argv [0]包含“/”(相对路径),则将其附加到cwd (假设它尚未更改)。

    • 否则,请在$PATH中搜索可执行文件argv[0]的目录。

    之后,检查可执行文件是否实际上不是符号链接可能是合理的。 如果它是相对于符号链接目录解析它。

    / proc方法中不需要此步骤(至少对于Linux)。 proc符号链接直接指向可执行文件。

    请注意,由调用进程正确设置argv[0]。 大多数时候都是正确的,但是有时候调用进程不可信(例如setuid可执行文件)。

  • 在Windows上:使用GetModuleFileName(NULL, buf, bufsize)

答案 1 :(得分:20)

如果您使用的是Windows,请使用GetModuleFileName()功能。

答案 2 :(得分:16)

请注意,以下注释仅限unix。

对这个问题的迂腐回答是,在所有情况下,没有一般方法正确回答这个问题。正如您所发现的那样,父进程可以将argv [0]设置为任何内容,因此无需与程序的实际名称或其在文件系统中的位置有任何关系。

但是,以下启发式通常有效:

  1. 如果argv [0]是绝对路径,则假设这是可执行文件的完整路径。
  2. 如果argv [0]是相对路径,即它包含/,请使用getcwd()确定当前工作目录,然后将argv [0]附加到其中。
  3. 如果argv [0]是一个普通单词,搜索$ PATH寻找argv [0],并将argv [0]附加到您找到它的目录中。
  4. 请注意,所有这些都可以通过调用相关程序的进程来规避。最后,您可以使用特定于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作为程序的真实路径。而且,事实上,它是 程序的真实路径,而不是您想要的路径。请注意,符号链接不会出现此问题,这在实践中比硬链接更常见。

    尽管这种方法原则上不可靠,但在大多数情况下,它在实践中运作良好。

答案 3 :(得分:10)

实际上不是答案,只是要记住的一个注意事项。

正如我们所看到的,在Linux和Unix中找到运行可执行文件的位置的问题非常棘手并且特定于平台。在做这件事之前,应该三思而后行。

如果您需要可执行位置来发现某些配置或资源文件,可能应该按照Unix方式在系统中放置文件:将配置文件放到/etc/usr/local/etc或当前用户主页目录,/usr/share是放置资源文件的好地方。

答案 4 :(得分:6)

在许多POSIX系统中,您可以检查位于/ proc / PID / exe下的simlink。几个例子:

# 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

答案 5 :(得分:4)

请记住,在Unix系统上,二进制文件自启动以来可能已被删除。它在Unix上完全合法且安全。最后我检查了Windows将不允许您删除正在运行的二进制文件。

/ proc / self / exe仍然可读,但它实际上不是一个有效的符号链接。这将是......奇怪的。

答案 6 :(得分:3)

对于Linux,您可以在名为binreloc的漂亮库中找到捆绑的/proc/self/exe方式,您可以在以下位置找到该库:

答案 7 :(得分:3)

在Mac OS X上,使用_NSGetExecutablePath

请参阅man 3 dyldthis answer类似的问题。

答案 8 :(得分:0)

我会

1)使用basename()函数:http://linux.die.net/man/3/basename
2)chdir()到该目录
3)使用getpwd()获取当前目录

这样你就可以得到一个整洁的完整形式的目录,而不是./或../ bin /.

如果这对您的程序很重要,也许您会想要保存并恢复当前目录。