Без доступа к argv[0], как я могу получить имя программы?



Я знаю, что имя программы передается в качестве первого аргумента, и следующий простой пример выведет его на стандартный вывод:



#include <iostream>
int main ( int argc, char *argv[] )
{
std::cout<<argv[0]<<std::endl;
}


Существует ли функция для получения имени программы?



EDIT



Я запускаю программу из оболочки, и приведенный выше код всегда будет печатать имя программы (я использую fedora 9, но я уверен, что он работает в других дистрибутивах).



Я обнаружил, что каталог /proc/self/ может содержать то, что я ищу, но я не смог найти что именно в этом справочнике.

555   6  

6 ответов:

Нет, такой функции не существует. Linux хранит имя программы в __progname, но это не публичный интерфейс. Если вы хотите использовать его для предупреждений / сообщений об ошибках, используйте функции err(3).

Если вам нужен полный путь запущенной программы, вызовите readlink on /proc/self/exe:

char *program_path()
{
    char *path = malloc(PATH_MAX);
    if (path != NULL) {
        if (readlink("/proc/self/exe", path, PATH_MAX) == -1) {
            free(path);
            path = NULL;
        }
    }
    return path;
}

(я полагаю, что __progname имеет базовое имя argv[0]. Проверьте источники glibc, чтобы быть уверенным.)

Это не гарантируется.

Обычно argv[0] содержит имя исполняемого файла, но можно вызвать исполняемый файл с помощью execve и установить его на что-то другое.

Одним словом: не полагайтесь на это.

Нет, это зависитполностью от того, что родительская программа помещает туда.

Семейство функций exec позволяет исполняемому имени полностью отличаться от передаваемого аргумента, и это поддерживается стандартом ISO C.

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

Так что нет., это только название программы, если оно доступно. А в предыдущем разделе говорится:

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

(Курсив мой).

Таким образом, даже их значения не диктуются стандартом, это полностью зависит от реализации. Этот означает, что имя программы может быть пустым, если среда хоста не предоставляет его, и ничего другого, если среда хоста предоставляет его.

Тем не менее, определение реализации имеет особое значение в стандартах ИСО-реализациядолжна документировать, как она работает. Так что даже UNIX, который может поместить все, что угодно, в argv[0] с семейством вызовов exec, должен (и делает) документировать это.

Аналогично (благодаря Chubsdad), C++03 утверждает:

" Если argc является ненулевые эти аргументы должны подаваться в argv[0] через argv[argc-1] в качестве указателей на начальные символы многобайтовых строк с нулевым завершением (NTMBSs) (17.3.2.1.3.2), а argv[0] должен быть указателем на начальный символ NTMBS, представляющий имя, используемое для вызова программы или "".

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

Другой способ сделать это в Linux-с помощью файловой системы proc. Я думаю, что /proc/self/exe - это ссылка на исполняемый файл.

В Википедии есть запись для procfs файловая система с большим количеством вкусностей.

Решение, специфичное для GLIBC:

#include <errno.h>
...
fprintf(stderr, "Program name is %s\n", program_invocation_name);

Из man invocation_name:

program_invocation_name содержит имя, которое было использовано для вызова вызывающей программы. Это то же самое, что и значение argv[0] в main(), с той разницей, что область действия program_invocation_name является глобальной.

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

Вы можете определить pid вашего процесса с помощью getpid (), а затем проверить содержимое /proc/[PID number] с помощью стандартных инструментов ввода-вывода.

Если вы используете GLib, вы можете использовать функцию g_get_prgname(). На Win32 он звонит GetModuleFileNameW(), на всем остальном он, кажется, возвращает NULL, хотя.

Comments

    Ничего не найдено.