无法访问argv [0],如何获取程序名称?

时间:2010-10-27 09:26:27

标签: c++ c linux command-line-arguments

我知道程序名称作为第一个参数传递,下一个简单示例将它打印到标准输出:

#include <iostream>
int main ( int argc, char *argv[] )
{
  std::cout<<argv[0]<<std::endl;
}

是否有获取程序名称的功能?

修改

我从shell启动程序,上面的代码将始终打印程序名称(我使用的是Fedora 9,但我相信它适用于其他发行版)。

我发现/ proc / self /目录可能包含我要查找的内容,但我无法找到该目录中的确切内容。

6 个答案:

答案 0 :(得分:19)

不,没有这样的功能。 Linux将程序名称存储在__progname中,但这不是公共接口。如果您想将此用于警告/错误消息,请使用err(3)函数。

如果您想要正在运行的程序的完整路径,请在readlink上致电/proc/self/exe

char *program_path()
{
    char *path = malloc(PATH_MAX);
    if (path != NULL) {
        if (readlink("/proc/self/exe", path, PATH_MAX) == -1) {
            free(path);
            path = NULL;
        }
    }
    return path;
}

(我相信__progname设置为argv[0]的基本名称。请查看glibc来源以确定。)

答案 1 :(得分:9)

这不能保证。

通常,argv[0]包含可执行文件名,但可以使用execve调用您的可执行文件并将其设置为其他名称。

总之:不要依赖于此。

答案 2 :(得分:6)

不,它完全取决于 在父程序放在那里。

exec函数系列允许可执行文件名与传入的参数完全不同,ISO C标准支持这一点。

  

如果argc的值大于零,则argv [0]指向的字符串表示程序名称;如果程序名不能从主机环境获得,则argv [0] [0]应为空字符。

所以不,如果名称可用,它只是程序名称。之前的部分说明:

  

如果argc的值大于零,则数组成员argv [0]到argv [argc-1]包含指向字符串的指针,这些指针由实现定义的值给出程序启动前的主机环境。

(我的斜体)。

因此,即使他们的价值观并非由标准决定,也完全取决于实施。这意味着如果主机环境不提供程序名称,则程序名称可以为空,如果主机环境确实提供程序名称,则程序名称可以为空。

但是,实现定义在ISO标准中具有特定含义 - 实现必须记录其工作原理。因此,即使是UNIX,它可以将任何喜欢的内容放入argv[0] exec系列调用中,也必须(并且确实)记录它。

同样(感谢Chubsdad),C ++ 03指出:

  

“如果argc非零,则这些参数应在argv [0]中通过argv [argc-1]提供,作为指向以null结尾的多字节字符串(NTMBS)(17.3.2.1.3.2)和argv的初始字符的指针[ 0]应该是指向NTMBS的初始字符的指针,该NTMBS表示用于调用程序或“”的名称。

所以,即使在那里,argv [0]也可能不包含任何东西,即使它确实如此,“代表名称”也是一个非常含糊的要求。它不必是可执行文件的完整路径名,甚至不包含用于调用它的命令


在Linux下执行此操作的另一种方法是使用proc文件系统。我认为/proc/self/exe是可执行文件的链接。

维基百科有一个procfs文件系统的条目,有许多好东西。

答案 3 :(得分:4)

GLIBC特定解决方案:

#include <errno.h>
...
fprintf(stderr, "Program name is %s\n", program_invocation_name);

来自man invocation_name

  

program_invocation_name包含用于调用调用程序的名称。这与argv[0]main()的值相同,但program_invocation_name的范围是全局的。

     

program_invocation_short_name包含用于调用调用程序的name的basename组件。也就是说,它与program_invocation_name的值相同,所有文本都包括最后的斜杠(/),如果有的话,删除。

答案 4 :(得分:3)

您可以使用getpid()确定进程的pid,然后使用标准I / O工具检查/ proc / [pid number]的内容。

答案 5 :(得分:2)

如果您使用GLib,则可以使用函数g_get_prgname()。在Win32上它调用GetModuleFileNameW(),在其他所有东西上都会返回NULL。