【发布时间】:2010-09-21 09:10:32
【问题描述】:
在我工作的 C / Unix 环境中,我看到一些开发人员使用 __progname 而不是 argv[0] 来获取使用消息。这有什么好处吗? __progname 和 argv[0] 有什么区别。便携吗?
【问题讨论】:
在我工作的 C / Unix 环境中,我看到一些开发人员使用 __progname 而不是 argv[0] 来获取使用消息。这有什么好处吗? __progname 和 argv[0] 有什么区别。便携吗?
【问题讨论】:
__progname 不是标准的,因此不可移植,更喜欢argv[0]。我想__progname 可以查找字符串资源以获取不依赖于您运行它的文件名的名称。但是argv[0] 会给你他们实际上运行它的名字,我会发现它更有用。
【讨论】:
使用__progname 允许您更改argv[] 数组的内容,同时仍保留程序名称。 getopt() 等一些常用工具在处理参数时会修改 argv[]。
为了可移植性,您可以在程序启动时将strcopy argv[0] 放入您自己的progname 缓冲区。
【讨论】:
我发现 argv[0] 至少有两个潜在问题。
首先,如果 execve() 调用者邪恶或粗心,则 argv[0] 或 argv 本身可能为 NULL。调用 execve("foobar", NULL, NULL) 通常是一种简单而有趣的方式来证明一个过于自信的程序员他的代码不是 sig11-proof。
还必须注意,argv 不会在 main() 之外定义,而 __progname 通常被定义为全局变量,您可以在您的 usage() 函数中甚至在调用 main() 之前使用(如非标准GCC 构造函数)。
【讨论】:
为此还有一个 GNU 扩展,因此可以从 main() 外部访问程序调用名称,而无需手动保存。但是,手动操作可能会更好。从而使其可移植,而不是依赖于 GNU 扩展。不过,我在这里提供了可用文档的摘录。
来自the on-line GNU C Library manual(今天访问):
“许多不从终端读取输入的程序被设计为在任何系统调用失败时退出。按照惯例,此类程序的错误消息应以程序名称开头,无目录。您可以找到该名称在变量program_invocation_short_name中;完整的文件名存储在变量program_invocation_name中。
变量:char * program_invocation_name
该变量的值是用于调用在当前进程中运行的程序的名称。与argv[0] 相同。请注意,这不一定是有用的文件名;通常它不包含目录名称。
变量:char * program_invocation_short_name
此变量的值是用于调用在当前进程中运行的程序的名称,删除了目录名称。 (也就是说,它等于program_invocation_name 减去最后一个斜线之前的所有内容,如果有的话。)
库初始化代码在调用 main 之前设置这两个变量。
可移植性说明:这两个变量是 GNU 扩展。如果您希望您的程序使用非 GNU 库,则必须将 argv[0] 的值保存在 main 中,然后自己删除目录名称。我们添加了这些扩展,以便编写独立的错误报告子例程,这些子例程不需要主程序的明确合作。”
【讨论】:
这是一种 BSD 主义,绝对不能移植。
【讨论】:
__progname 只是 argv[0],此处其他回复中的示例显示了使用它的弱点。虽然也不是可移植的,但我在 /proc/self/exe(Linux、Android)上使用 readlink,并读取 /proc/self/exefile (QNX) 的内容。
【讨论】:
如果您的程序是使用例如符号链接运行的,则 argv[0] 将包含该链接的名称。
我猜 __progname 将包含实际程序文件的名称。
无论如何,argv[0] 是由 C 标准定义的。 __progname 不是。
【讨论】: