Windows与Linux GCC argv [0]值

时间:2011-10-29 20:38:59

标签: c++ windows linux path

  

可能重复:
  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”。这打破了我的申请!关于如何确保路径在两个系统上都是绝对的任何想法?

3 个答案:

答案 0 :(得分:9)

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

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

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

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

$ stat /usr/bin/git
234881026 459240 -rwxr-xr-x 109 root wheel 0 2500640 "Oct 29 08:51:50 2011" "May 16 18:44:05 2011" "Jul 26 20:28:29 2011" "May 16 18:44:05 2011" 4096 4888 0 /usr/bin/git
$ stat /usr/bin/git-receive-pack 
234881026 459240 -rwxr-xr-x 109 root wheel 0 2500640 "Oct 29 08:51:50 2011" "May 16 18:44:05 2011" "Jul 26 20:28:29 2011" "May 16 18:44:05 2011" 4096 4888 0 /usr/bin/git-receive-pack

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

中看到这种情况

答案 1 :(得分:4)

argv数组

argv[0]是一个与其他参数类似的参数:它可以是任意NUL终止的字节字符串。它可以是空字符串。无论启动过程是什么,它都是

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

要使用zsh(带有其他shell的dunno)调用具有其他值的程序,请使用:

ARGV0=whatever_you_want some_program arguments

如果您确实需要可执行文件的路径,则无法在Unix上使用命令行。

仅限Linux

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

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

重命名和软链接

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

在重命名的情况下,soft-but-magic-link将遵循重命名。如果有多个硬链接,它将遵循所使用的特定硬链接的名称。 (因此,在Linux下,同一文件的不同硬链接并不完全相同。)

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

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

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

安全注意事项

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

readlink时,返回的值可能会引用另一个文件。 (当然,open的结果readlink始终存在不可避免的竞争条件。)

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

答案 2 :(得分:3)

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

如果从命令提示符.\bin\Test通过argv[0]调用程序时{38},这似乎是MinGW运行时中的错误。"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]