关于c ++:如何在C中找到可执行文件的位置?

How do I find the location of the executable in C?

本问题已经有最佳答案,请猛点这里访问。

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

(argv[0]的问题是它没有给出完整的路径。)


总结:

  • 在与/proc的unixes上,真正直接和可实现的方法是:

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

    • readlink("/proc/curproc/file", buf, bufsize)(自由标准)

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

  • 在不带/proc的unixes上(即,如果上述失败):

    • 如果argv[0]以"/"(绝对路径)开头,则这是路径。

    • 否则,如果argv[0]包含"/"(相对路径),则将其附加到cwd(假设还没有改变)。

    • 否则,在$PATH中搜索目录以查找可执行的argv[0]

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

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

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

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


如果使用的是Windows,请使用getModuleFileName()函数。


请注意,以下注释仅适用于Unix。

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

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

  • 如果argv[0]是绝对路径,则假定这是可执行文件的完整路径。
  • 如果argv[0]是相对路径,即它包含一个/,则使用getcwd()确定当前工作目录,然后将argv[0]附加到它。
  • 如果argv[0]是一个普通字,请在$path中搜索argv[0],然后将argv[0]附加到您在其中找到它的任何目录中。
  • 注意,所有这些都可以通过调用相关程序的过程来规避。最后,您可以使用特定于Linux的技术,如EMG-2所提到的。在其他操作系统上可能也有类似的技术。

    即使假设上面的步骤为您提供了一个有效的路径名,您仍然可能没有实际想要的路径名(因为我怀疑您实际想要做的是在某个地方找到一个配置文件)。存在硬链接意味着您可以有以下情况:

    1
    2
    3
    4
    -- 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成为程序的真正路径。事实上,这是一条通往程序的真正路径,而不是你想要的路径。注意,这个问题不会发生在符号链接上,符号链接在实践中比硬链接更常见。

    尽管这种方法在原则上是不可靠的,但在大多数情况下,它在实践中都能很好地工作。


    实际上不是一个答案,只是一个需要记住的注释。

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

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


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

    1
    2
    3
    4
    # 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仍然是可读的,但实际上它不是一个有效的符号链接。这将是…奇怪的。


    在Mac OS X上,使用_NSGetExecutablePath

    man 3 dyld和类似问题的答案。


    对于Linux,您可以在一个名为binreloc的不错的库中找到/proc/self/exe的方法,该库位于:

    • 网址:http://autopackage.org/docs/binreloc/


    我愿意

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

    这样,您将得到一个整洁、完整的目录,而不是./或../bin/。

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