Использование '__progname' вместо argv [0] - PullRequest
15 голосов
/ 08 ноября 2008

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

Ответы [ 7 ]

18 голосов
/ 08 ноября 2008

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

7 голосов
/ 08 ноября 2008

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

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

6 голосов
/ 09 июня 2010

Для этого также имеется расширение 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. "

5 голосов
/ 09 ноября 2008

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

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

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

4 голосов
/ 08 ноября 2008

Это BSDism, и определенно не переносимый.

2 голосов
/ 14 января 2014

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

0 голосов
/ 08 ноября 2008

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...