Использование 'progname' вместо argv[0]

в среде C / Unix, в которой я работаю, я вижу, что некоторые разработчики используют __progname вместо argv[0] для сообщений usage (). Есть ли в этом какое-то преимущество? В чем разница между __progname и argv[0]. Он портативный?

7 ответов


__progname не стандартный и поэтому не портативный, предпочитают argv[0]. Я полагаю __progname может искать строковый ресурс, чтобы получить имя, которое не зависит от имени файла, который вы запустили. Но!--1--> даст вам имя они на самом деле запустил его, как я нашел бы более полезным.


используя __progname позволяет изменять содержимое argv[] массив сохраняя при этом имя программы. Некоторые из распространенных инструментов, таких как getopt() изменить argv[] по мере обработки аргументов.

для переносимости, вы можете strcopy argv[0] на свой progname буфер при запуске программы.


для этого также есть расширение GNU, так что можно получить доступ к имени вызова программы извне main() без сохранения его вручную. Однако было бы лучше сделать это вручную; таким образом, сделать его портативным, а не полагаться на расширение GNU. Тем не менее, я приведу здесь выдержку из имеющейся документации.

С он-лайн руководство библиотеки GNU C (по состоянию на сегодня):

" много программ которые не читают входной сигнал от терминал предназначен для выхода при сбое любого системного вызова. По соглашению сообщение об ошибке из такой программы должно начинаться с имени программы, без каталогов. Вы можете найти это имя в переменную 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, а затем снимите имена каталогов самостоятельно. Мы добавили эти расширения, чтобы можно было писать автономные подпрограммы отчетов об ошибках, которые не требуют явного сотрудничества от main."


Это BSDism, и определенно не портативный.


Я вижу по крайней мере две потенциальные проблемы с argv[0].

во-первых, argv[0] или сам argv может быть нулевым, если вызывающий execve() был злым или достаточно небрежным. Вызов execve ("foobar", NULL, NULL) обычно является простым и интересным способом доказать уверенному программисту, что его код не является sig11-proof.

следует также отметить, что argv не будет определен вне main (), в то время как _ _ progname обычно определяется как глобальная переменная, которую вы можете использовать из своей функции usage () или даже до вызова main () (например, нестандартных конструкторов GCC).


__progname - это просто argv[0], и примеры в других ответах здесь показывают недостатки его использования. Хотя и не портативный, я использую readlink on/proc/self /exe (Linux, Android) и читаю содержимое/proc/self / exefile (QNX).


Если ваша программа была запущена с использованием, например, символической ссылки, argv[0] будет содержать имя этой ссылки.

Я предполагаю, что _ _ progname будет содержать имя фактического файла программы.

в любом случае argv[0] определяется стандартом C. __progname нет.