Доступ к аргументам командной строки без использования char ** argv в main - PullRequest
5 голосов
/ 18 марта 2010

Есть ли способ получить доступ к аргументам командной строки, не используя аргумент для main? Мне нужно получить к нему доступ в другой функции, и я бы предпочел не передавать ее.

Мне нужно решение, которое обязательно работает только в Mac OS и Linux с GCC.

Ответы [ 6 ]

8 голосов
/ 13 июля 2014

Я не знаю, как это сделать на MacOS, но я подозреваю, что трюк, который я опишу здесь, можно перенести на MacOS с небольшим количеством перекрестного чтения.

В linux вы можете использовать так называемый раздел .init_array двоичного файла ELF, чтобы зарегистрировать функцию, которая вызывается во время инициализации программы (до вызова main ()). Эта функция имеет ту же сигнатуру, что и обычная функция main (), за исключением того, что она возвращает «void». Таким образом, вы можете использовать эту функцию для запоминания или обработки argc, argv [] и evp [].

Вот код, который вы можете использовать:

static void my_cool_main(int argc, char* argv[], char* envp[])
{
    // your code goes here
}

__attribute__((section(".init_array"))) void (* p_my_cool_main)(int,char*[],char*[]) = &my_cool_main;

PS: Этот код также можно поместить в библиотеку, поэтому он должен соответствовать вашему случаю. Это даже работает, когда ваша prgram запускается с valgrind - valgrind не запускает новый процесс, и в результате / proc / self / cmdline показывает исходную командную строку valgrind.

PPS: имейте в виду, что во время этого очень раннего выполнения программы многие подсистемы еще не полностью инициализированы - я попробовал подпрограммы ввода / вывода libc, они, кажется, работают, но не полагаются на это - даже глобальные переменные могут еще не быть построенным и т.д ...

3 голосов
/ 18 марта 2010

Вы можете скопировать их в глобальные переменные, если хотите.

3 голосов
/ 18 марта 2010

Я не думаю, что вы должны делать это, поскольку среда выполнения C подготовит аргументы и передаст их в основную систему с помощью int argc, char **argv, не пытайтесь манипулировать поведением, взломав его, так как оно будет в основном непереносимым или возможно неопределенным поведение!! Придерживайтесь правил, и у вас будет мобильность ... нет другого способа сделать это, кроме как нарушить его ...

2 голосов
/ 21 января 2014

В Linux вы можете открыть /proc/self/cmdline (при условии, что присутствует /proc) и выполнить синтаксический анализ вручную (это необходимо, только если вам нужно argc / argv перед main() - например, в глобальном конструктор - иначе лучше передать их через глобальные переменные).

Дополнительные решения доступны здесь: http://blog.linuxgamepublishing.com/2009/10/12/argv-and-argc-and-just-how-to-get-them/

Да, это грубо и непереносимо, но если вы решаете практические проблемы, вам может быть все равно.

0 голосов
/ 19 марта 2010

Есть ли какая-то причина, по которой передача указателя на уже занятое пространство так плоха? Вы не получите никакой реальной экономии за счет исключения аргумента для рассматриваемой функции, и вы можете запустить интересный показ фейерверков. Обход стека вызовов main () с помощью творческого хакерства обычно заканчивается неопределенным поведением или зависимостью от поведения, специфичного для компилятора. И то и другое плохо для функциональности и мобильности соответственно.

Имейте в виду, что рассматриваемые аргументы указатели на аргументы, они будут занимать пространство независимо от того, что вы делаете. Удобство их индекса столь же дешево, как sizeof (int), я не вижу причин не использовать его.

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

0 голосов
/ 18 марта 2010

Можно.Большинство платформ предоставляют глобальные переменные __argc и __argv.Но опять же, я поддерживаю комментарий zneak.

PS Используйте boost :: program_options для их анализа.Пожалуйста, не делайте этого иначе в C ++.

...