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

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

7 ответов

Решение

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

С помощью __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 ".

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

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

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

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

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

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

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

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

Другие вопросы по тегам