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

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

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

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

редактировать

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

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

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] включительно должны содержать указатели на строки, которые задаются реализация-определено значения среды хоста до запуска программы.

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

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

однако реализация-определенная имеет конкретное значение в стандартах ISO-реализация должны документ как это работает. Так что даже 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 содержит базовый компонент name, который использовался для вызова вызывающей программы. То есть это то же значение, что и program_invocation_name, со всем текстом до и включая финал Слэш (/), если таковой имеется, удаляется.


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


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