2008-11-07 2 views
15

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

ответ

18

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

+3

Рассмотрите: execl ("/ bin/sh "," hot potatoes "," -c "," echo $ 0 - Hi ", (char *) 0); Прекрасно работает, argv [0] -« горячий картофель », отгоняет« горячий картофель - Привет ». делать с именем исполняемого файла, который был запущен. – 2008-11-08 08:41:00

+2

Несмотря на предыдущий комментарий, я согласен с тем, что argv [0] более портативен. И только несколько программ беспорядок с argv [0], как это, но любой злоумышленник может это сделать. Будьте осторожны с b принимая критические решения по argv [0]. – 2008-11-08 08:42:43

6

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

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

+0

GNU getopt() messes with argv; версии, не относящиеся к GNU, обычно не делают этого. – 2008-11-08 08:43:20

4

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

0

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

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

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

4

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

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

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

6

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

С the on-line GNU C Library manual (доступ сегодня).

«Многие программы, которые не читают ввод с терминала предназначены для выхода, если любой системный вызов не По соглашению, сообщение об ошибке от такой программы должна начинаться с . название программы, Sans каталоги Вы можете найти это имя в переменной program_invocation_short_name, полное имя файла хранится переменная program_invocation_name

  • Variable: обугленного * program_invocation_name . Значение этой переменной - это имя, которое использовалось для вызова программы, запущенной в текущем процессе. Это то же самое, что и argv[0]. Обратите внимание, что это необязательно является полезным именем файла; часто он не содержит имен каталогов.

  • Variable: символ * program_invocation_short_name значение этой переменной является имя, которое используется для вызова программы, выполняемой в текущем процессе, с именами каталогов удалены. (То есть, это то же самое, как program_invocation_name минус все до последней косой черты, если таковые имеются.)

Библиотека код инициализации устанавливает обе из этих переменных перед вызовом основной.

Примечание по переносимости: Эти две переменные являются расширениями GNU. Если вы хотите, чтобы ваша программа работала с библиотеками, отличными от GNU, вы должны сохранить в главном файле значение argv[0], а затем сами удалить имена каталогов. Мы добавили эти расширения, чтобы можно было писать автономные подпрограммы отчетности об ошибках, которые не требуют явного сотрудничества с основными ».

1

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

Смежные вопросы