【问题标题】:Windows vs. Linux GCC argv[0] value [duplicate]Windows 与 Linux GCC argv[0] 值 [重复]
【发布时间】:2011-12-17 23:57:21
【问题描述】:

可能重复:
Get path of executable

我正在使用 MinGW、gcc 4.4.3 在 Windows 上编程。当我像这样使用主要功能时:

int main(int argc, char* argv[]){
    cout << "path is " << argv[0] << endl;
}

在 Windows 上,我得到一个像这样的完整路径:“C:/dev/stuff/bin/Test”。然而,当我在 Linux 上运行相同的应用程序时,我得到了某种相对路径:“bin/Test”。它破坏了我的应用程序!关于如何确保两个系统上的路径都是绝对路径的任何想法?

【问题讨论】:

  • 我有理由确定没有办法保证任何这样的事情。如果您需要可执行文件的绝对路径,则需要使用 argv[0] 以外的其他方式来获取它。
  • 这也不应该在 Windows 上工作。您是从命令行启动程序还是通过资源管理器启动程序?
  • 我正在使用生成文件。 makefile 命令是 bin/test。奇怪,是不是……

标签: c++ windows linux path


【解决方案1】:

不,没有。在 Linux 上的大多数 shell 中,argv[0] 包含用户键入 以运行二进制文件的确切内容。这允许二进制文件根据用户类型执行不同的操作。

例如,具有多个不同命令行命令的程序可能会安装一次二进制文件,然后将各种不同的命令硬链接到同一个二进制文件。例如,在我的系统上:

$ ls -l /usr/bin/git* -rwxr-xr-x 109 根轮 2500640 5 月 16 日 18:44 /usr/bin/git -rwxr-xr-x 2 根轮 121453 5 月 16 日 18:43 /usr/bin/git-cvsserver -rwxr-xr-x 109 根轮 2500640 5 月 16 日 18:44 /usr/bin/git-receive-pack -rwxr-xr-x 2 根轮 1021264 5 月 16 日 18:44 /usr/bin/git-shell -rwxr-xr-x 109 根轮 2500640 5 月 16 日 18:44 /usr/bin/git-upload-archive -rwxr-xr-x 2 根轮 1042560 5 月 16 日 18:44 /usr/bin/git-upload-pack -rwxr-xr-x 1 根轮 323897 5 月 16 日 18:43 /usr/bin/gitk

请注意其中一些文件的大小完全相同。更多调查显示:

$统计/usr/bin/git 234881026 459240 -rwxr-xr-x 109 根轮 0 2500640“2011 年 10 月 29 日 08:51:50”“2011 年 5 月 16 日 18:44:05”“2011 年 7 月 26 日 20:28:29”“5 月 16 日 18:44: 05 2011" 4096 4888 0 /usr/bin/git $ stat /usr/bin/git-receive-pack 234881026 459240 -rwxr-xr-x 109 根轮 0 2500640“2011 年 10 月 29 日 08:51:50”“2011 年 5 月 16 日 18:44:05”“2011 年 7 月 26 日 20:28:29”“5 月 16 日 18:44: 05 2011" 4096 4888 0 /usr/bin/git-receive-pack

inode 编号 (459240) 相同,因此这是指向磁盘上同一文件的两个链接。运行时,二进制文件使用argv[0] 的内容来确定要执行的函数。你可以在code for Git's main() 中看到这个(有点)。

【讨论】:

  • 更不用说调用exec* 系列函数之一来运行您的代码的任何代码都可以为argv[0] 放置它想要的任何东西。
【解决方案2】:

argv 数组

argv[0] 和其他参数一样是一个参数:它可以是任意以 NUL 结尾的字节字符串。它可以是空字符串。这是启动过程想要的任何东西。

默认情况下,将argv[0] 设置为用于命名程序的shell:在$PATH 中查找的名称、相对路径或绝对路径。它可以是符号链接或常规文件。

要调用具有其他值的程序,使用 zsh(不知道其他 shell)使用:

ARGV0=whatever_you_want some_program 参数

如果你真的需要可执行文件的路径,你不能在 Unix 上使用命令行。

仅限 Linux

在 Linux 上:/proc/self/exe 是指向可执行文件的符号链接。

你可以readlink它。也可以直接statopen

重命名和软链接

普通的软链接是一个哑字符串,不知道它的目标会发生什么(如果它存在的话)。但是/proc/self/exe 软链接很神奇。

在重命名的情况下,软但魔术链接将跟随重命名。如果有多个硬链接,它将遵循所使用的特定硬链接的名称。 (所以在 Linux 下,同一个文件的不同硬链接并不完全等价。)

如果这个硬链接被取消链接,我认为" (deleted)"被附加到符号链接的值上。请注意,这是一个有效的文件名,因此另一个不相关的文件可以使用该名称。

无论如何,符号链接是指向文件的硬链接,因此您可以直接statopen

如果二进制文件在另一个系统上被重命名或取消链接,而不是启动可执行文件的系统,我认为你不能指望网络文件系统上的任何东西。

安全注意事项

当您的程序开始使用/proc/self/exe 特殊文件时,用于启动您的程序的文件可能是unlinked 或renamed。如果程序具有特权(SUID 或 Set Capabilities),则应认真对待这一点:即使用户没有对原始“Set Something”二进制文件的写访问权限,他也可以建立一个硬链接到它,如果他对同一文件系统上的目录具有写入权限,因此如果正在运行的特权二进制文件,他可能能够更改名称。

当您readlink 时,返回的值可能引用另一个文件。 (当然,openreadlink 的结果总是不可避免的。)

与往常一样,NFS 并不提供与本地文件系统相同的所有保证。

【讨论】:

    【解决方案3】:

    无法确保argv[0] 是绝对路径,因为它应该正是用户调用程序的方式。因此,如果在 Linux 命令行上通过./bin/Test 调用程序,那么argv[0] 应该正好是"./bin/Test"

    如果当您从命令提示符通过.\bin\Test 调用程序时,这似乎是MinGW 运行时中的一个错误,argv[0]"C:/dev/stuff/bin/Test"。使用最新的 MinGW(gcc 版本 4.5.2),通过.\bin\Test 调用二进制文件意味着argv[0]".\bin\Test"。通过.\bin\Test 调用的Microsoft Visual C++ 构建的二进制文件(cl 版本16.00.40219.01)也有".\bin\Test" 用于argv[0]

    【讨论】:

    • 它应该是用户调用程序的确切方式。除非它是一个登录 shell,它会在前面加上一个破折号。
    • C 标准 (5.1.2.2.1p2) 说“如果 argc 的值大于零,则 argv[0] 指向的字符串代表 程序名称 ";故意不清楚“程序名称”是什么或 argv[0] 如何“表示”它。 POSIX 基本上说 argv[0] 是在调用程序时传递给 exec*() 函数的任何内容——这意味着它取决于调用 shell。
    • @ninjalj:我不知道。这很有趣:)
    • @KeithThompson:好的,所以这不是 MinGW 错误。很高兴知道。
    猜你喜欢
    • 2013-11-02
    • 2013-08-29
    • 1970-01-01
    • 2014-09-22
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多