Getopt возвращает -1, но у него есть действительные данные

#c #getopt

Вопрос:

Я запускаю свою программу в GDB, чтобы определить, почему getopt возвращает -1, и я вижу, что у него явно есть действительные данные. Я не получаю argv/argc из командной строки программы, я генерирую его сам, но это все еще явно действительные данные.

(Соответствующий) код:

     char* argv[4];                                                                                                                         
    printf("calling create_argvn");                                                                                                       
    int argc = create_argv(argstring, argv, 4);                                                                                            
    int opt;                                                                                                                               
    int myBuf = 0, total_mbufs = 0;                                                                                                        
    bufs_list* bufToUse = einf->bufs_head;                                                                                                                                                                                                                                        
    while ((opt = getopt(argc, argv, "f:t:")) != -1){                                                                                              
    printf("opt is %sn", opt);                                                                                                            
    switch(opt){                                                                                                                                   
        case 'f':                                                                                                                                      
        fd = fopen(optarg, "r");                                                                                                               
        break;                                                                                                                         
        case 't':                                                                                                                                      
        fsize = atoi(optarg);                                                                                                                  
        break;                                                                                                                         
        default: break;                                                                                                                
    }                                                                                                                              
}    
 

create_argv: (исходя из того, что я могу сказать с помощью GDB)

 int create_argv(char* string, char* argv[], int nargs){                                                                                                                                                                                                                                                                                                                                                                                                                                                 
    int idx = 0;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    char* s;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    char* p;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    printf("in create_argvn");                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
    for (s = string, p = string; *s != '' amp;amp; *s != 'n'; s  ){                                                                                                                                                                                                                                                                                                                                                                                                                                            
        printf("%cn", *s);                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
        if (*s == ' '){                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
            *s = '';                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
            argv[idx  ] = p;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
            printf("%sn", p);                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
            p =   s;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
            if (idx == nargs) return idx; //bail out if we can't fit any more                                                                                                                                                                                                                                                                                                                                                                                                                       
        }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
    *s = '';                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
    argv[idx  ] = p;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
    printf("%sn", p);                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
    p =   s;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    return idx; //equivalent to argc
}                                                                                                                           
 

Итак, gdb говорит, что все в идеальном рабочем состоянии:

 (gdb) p opt
$2 = -1
(gdb) p argc
$3 = 2
(gdb) p argv
$4 = {0x7a9935 "-f", 0x7a9938 "file.txt", 0x2f76006f666e692f <Add
 

(argv[2] недопустим, но это нормально, потому что argc-это только 2).

Так что же не так с getopt? У него явно есть действительный argc, действительный argv, но он отказывается признавать, что у него есть действительные данные.

Изменить: вывод показывает, что цикл while никогда не выполняется —

 calling create_argv
in create_argv
-
f

-f 
i
l
e
.
t
x
t
file.txt
no file loaded (did you specify -f filename?). Refusing to load an empty file
 

Комментарии:

1. Это не похоже getopt на возврат -1 при ошибке, а скорее, когда он достигает конца аргументов. Вот справочная страница для getopt . Можете ли вы добавить вывод вашей программы к вопросу?

2. Добавлен вывод @GuyMarino — цикл while никогда не запускается, несмотря на наличие аргументов

3. Хорошее замечание по поводу printf. Я не думаю, что это могло бы вызвать эту проблему, но хорошо бы помнить об этом

4. Хорошо, я не уверен, что это исправит ситуацию, но попробуйте выполнить цикл «пока» с отрицательным условием и выведите значения optopt и optarg . Они могут содержать то, что вы ищете. Если вы не хотите переписывать свой код, просто проверьте их в отладчике после выполнения цикла.

5. optarg и optopt равны 0 сразу после выполнения цикла (неудачной первой итерации)

Ответ №1:

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