int main(int argc, char* argv[]){
cout << "path is " << argv[0] << endl;
}
在Windows系统下,我得到的是完整路径:"C:/dev/stuff/bin/Test"。然而,在Linux系统下运行同样的应用程序时,我得到的是一种相对路径:"bin/Test"。这破坏了我的应用程序!有没有办法确保在两个系统上路径都是绝对路径?
int main(int argc, char* argv[]){
cout << "path is " << argv[0] << endl;
}
在Windows系统下,我得到的是完整路径:"C:/dev/stuff/bin/Test"。然而,在Linux系统下运行同样的应用程序时,我得到的是一种相对路径:"bin/Test"。这破坏了我的应用程序!有没有办法确保在两个系统上路径都是绝对路径?
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]
的内容来确定要执行哪个函数。你可以在 Git 的 main() 函数的代码中看到这一点(有点)。
exec*
函数族中的任一函数来运行您的代码的任何代码都可以将任何内容放入argv[0]
。 - Adam Rosenfieldargv[0]
就像其他参数一样:它可以是任意以NUL结尾的字节字符串。它可以是空字符串。它是启动进程想要的任何内容。
默认情况下,shell会将argv[0]
设置为用于命名程序的任何内容:在$PATH
中查找的名称、相对路径或绝对路径。它可以是符号链接或常规文件。
要使用其他值调用程序,在zsh(不知道其他shell)中使用:
ARGV0=你想要的内容 some_program 参数
如果你真的需要可执行文件的路径,则不能在Unix上使用命令行。
在Linux上:/proc/self/exe
是可执行文件的符号链接。
你可以使用readlink
读取它。你也可以直接使用stat
或open
打开它。
普通的软链接只是一个愚蠢的字符串,不知道其目标发生了什么(如果目标存在)。但/proc/self/exe
的软链接是魔法链接。
如果重命名,软链接将跟随重命名。如果有多个硬链接,它将遵循使用的特定硬链接的名称。(因此,在Linux下,对同一文件的不同硬链接并不完全等效。)
如果取消链接这个硬链接,我认为"(已删除)"
会附加到符号链接的值上。请注意,这是一个有效的文件名,因此另一个不相关的文件可能具有该名称。
在任何情况下,符号链接是文件的硬链接,因此你可以直接使用stat
或open
打开它。
如果在启动可执行文件的系统以外的其他系统上重命名或取消链接二进制文件,则无法在网络文件系统上保证任何内容。
当你的程序使用/proc/self/exe
特殊文件时,启动程序所使用的文件可能会被unlink
或rename
。如果程序是特权程序(SUID或设置了能力),则应该认真对待此问题:即使用户没有写访问权限,也可能通过在相同文件系统上的目录中具有写访问权限来创建到原始“设置某些内容”的二进制文件的硬链接,从而可能更改正在运行的特权二进制文件的名称。
在你readlink
的时候,返回的值可能会引用另一个文件。(当然,使用readlink
的结果进行open
始终存在不可避免的竞争条件。)
通常情况下,NFS无法提供与本地文件系统相同的所有保证。
无法确保argv [0]
是绝对路径,因为它应该恰好是用户调用程序的方式。因此,如果在Linux命令行上通过./bin/Test
调用程序,则argv [0]
应该恰好是"./bin/Test"
。
如果当您通过命令提示符通过.\bin\Test
调用程序时,argv [0]
是"C:/dev/stuff/bin/Test"
,则似乎是MinGW运行时中的一个错误。使用最新的MinGW(gcc版本4.5.2),通过.\bin\Test
调用二进制文件意味着argv [0]
是".\bin\Test"
。通过Microsoft Visual C++构建的二进制文件(cl版本16.00.40219.01)通过.\bin\Test
调用也具有".\bin\Test"
作为argv [0]
。
argv[0]
是在调用程序时传递给exec*()
函数的内容,这意味着它取决于调用shell。 - Keith Thompson