Работают ли C getopt и getopt_long только для основных аргументов?

вопрос довольно ясен, интересно, потому что человек говорит

Функция getopt() анализирует аргументы командной строки.

И я пытаюсь использовать его с другой функцией, которая имеет ту же сигнатуру, что и основная, а argc и argv получаются с wordexp, поэтому все кажется таким же, но при вызове getopt я получаю ошибку сегментации сразу после вызова getopt_long.

#define   OPT_HELP    'h'
#define   OPTL_HELP   "help"
#define   OPT_MESS    'm'
#define   OPTL_MESS   "message"

#define   OPT_STRING  "hm:"

struct option longopts[] = {
  {OPTL_HELP,     no_argument, 0, OPT_HELP},
  {OPTL_MESS,     required_argument, 0, OPT_MESS},
  {0, 0, 0, 0}
};

#define FLAG_MESS 1

void cmd_chat(int argc, char **argv)
{
  int c, indexptr;
  short flag = 0;
  char message[481];
  while ((c = getopt_long(argc, argv, OPT_STRING,
          longopts, &indexptr)) != -1) {
    debug(MAGENTA "cmd_chat", MAGENTA "c value: %d", c);
    switch (c) {
      case OPT_HELP:
        debug(MAGENTA "cmd_chat", MAGENTA "calling help");
        help(argv[0]);
        return;
        break;
      case OPT_MESS:
        flag |= FLAG_MESS;
        strncpy(message, optarg, 481);
        break;
      default:
        usage(argv[0]);
        break;
    }
  }


[...]

Возможно, это так, но если да, то мне интересно, почему это так, а также почему мы должны передавать argc и argv в getopt(_long).

Спасибо.


person Nicolas Scotto Di Perto    schedule 20.04.2016    source источник
comment
Одно допущение, которое не часто упоминается, заключается в том, что вы вызываете getopt() и др. последовательно с одними и теми же значениями для argc и argv, а не меняете список при каждом вызове. Если вы используете getopt() для обработки аргументов командной строки, а затем используете его для доступа к какому-то другому набору аргументов, вы можете — не обязательно обязательно — столкнуться с проблемами. Вы делаете что-нибудь подобное? (По сути, параллелизм не предусмотрен — он не ориентирован на многопотоковое исполнение — и нет возможности для повторного использования. Обычно существует полунедокументированный способ перезагрузки системы, чтобы она начиналась заново, но он бывает разным.)   -  person Jonathan Leffler    schedule 21.04.2016
comment
Никакие вызовы getopt не исходят из одного и того же потока и поэтому выполняются последовательно.   -  person Nicolas Scotto Di Perto    schedule 21.04.2016


Ответы (1)


И getopt(), и getopt_long() будут работать со всеми правильными char ** и int, нет никакой разницы между argv и любым другим char **. Если вы передадите argv и argc или их копии из main в свою функцию и вызовете getopt() оттуда, все будет работать. Покажите, как ваша функция получила argc и argv;

person coredump    schedule 20.04.2016
comment
Хорошо. Я действительно не понимаю, откуда взялась эта ошибка сегментации... Я напечатал значения argv перед вызовом команды (это программа оболочки) chat -h, argv хорошо проанализирован, а argc установлен на 2. Я пробовал простой вызов getopt без какого-либо цикла while, за которым немедленно следует печать возвращаемого значения, и я все еще получаю ошибку сегментации. Я вижу, что это исходит от вызова getopt_long, потому что печать еще не сделана. - person Nicolas Scotto Di Perto; 21.04.2016
comment
Итак, вы дважды вызываете getopt в своей программе? Если вы вызываете его дважды, вам нужно установить optind в 0 перед вторым вызовом. И предоставьте mcve: stackoverflow.com/help/mcve - person coredump; 21.04.2016
comment
Я прокомментировал цикл while и заменил его одним вызовом getopt_long, и я получаю ошибку сегментации, поэтому без двойных вызовов, но я попытался установить optind в 0 перед первым вызовом, и это работает. Я не вижу этого в мужчине. - person Nicolas Scotto Di Perto; 21.04.2016