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

问题描述 投票:0回答:9

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

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

c++ c linux unix path
9个回答
225
投票

总结一下:

  • 在具有

    /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)


27
投票

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


19
投票

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

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

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

如果
    argv[0]
  1. 是绝对路径,则假设这是可执行文件的完整路径。
    如果
  2. argv[0]
  3. 是相对路径,即包含
    /
    ,则用
    getcwd()
    确定当前工作目录,然后将
    argv[0]
    附加到它。
    如果 
  4. argv[0]
  5. 是一个普通单词,请搜索
    $PATH
    查找
    argv[0]
    ,并将
    argv[0]
    附加到您在其中找到它的任何目录。
    
    
  6. 请注意,所有这些都可以通过调用相关程序的进程来规避。 最后,您可以使用 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

作为程序的真实路径。 事实上,它是程序的真正路径,只是不是您想要的路径。 请注意,符号链接不会出现此问题,符号链接在实践中比硬链接更常见。

尽管这种方法原则上不可靠,但它在实践中对于大多数目的来说足够有效。
    

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


13
投票

如果您需要可执行位置来发现某些配置或资源文件,也许您应该遵循在系统中放置文件的 Unix 方式:将配置放入

/etc

/usr/local/etc

或当前用户主目录中,然后

/usr/share
是放置资源文件的好地方。
    
请记住,在 Unix 系统上,二进制文件自启动以来可能已被删除。它在 Unix 上是完全合法且安全的。上次我检查过 Windows 不允许您删除正在运行的二进制文件。


8
投票

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


6
投票

在 Mac OS X 上,使用 

4
投票

请参阅类似问题的
man 3 dyld

此答案

对于 Linux,您可以在一个名为 binreloc 的漂亮库中找到

/proc/self/exe

3
投票

http://autopackage.org/docs/binreloc/

  • 我愿意

1
投票
使用

dirname()

函数:
    http://linux.die.net/man/3/dirname
  1. 
    chdir()
    到该目录
  2. 使用 
    getcwd()
    获取当前目录
  3. 这样您就能获得整洁、完整的目录,而不是 
    ./
../bin/

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

© www.soinside.com 2019 - 2024. All rights reserved.