Использование '__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),
__progname - просто argv[0], и примеры в других ответах здесь показывают слабые стороны его использования. Хотя и не переносимый, я использую readlink в /proc/self/exe (Linux, Android) и читаю содержимое /proc/self/exefile (QNX).
Если ваша программа была запущена с использованием, например, символической ссылки, argv[0] будет содержать имя этой ссылки.
Я предполагаю, что __progname будет содержать имя самого файла программы.
В любом случае argv [0] определяется стандартом C. __progname нет.