2017-06-21 2 views
0

pour un projet scolaire je dois utiliser getopt_long() ou getopt_long_only(). Voici ma boucle:segfault avec getopt_long()

while ((get_opt_err = getopt_long(argc, argv, "p:x:y:n:c:f:h", 
        &help_opt, NULL)) != -1) 

J'ai un segfault rapporté dans valgrind comme ça:

==2971== Memcheck, a memory error detector 
==2971== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==2971== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info 
==2971== Command: ./zappy_server --h 
==2971== 
==2971== Conditional jump or move depends on uninitialised value(s) 
==2971== at 0x4F0B23E: _getopt_internal_r (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C240: _getopt_internal (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C2BD: getopt_long (in /usr/lib/libc-2.25.so) 
==2971== by 0x400C3D: getopt_server_parsing (getopt_server_parsing.c:42) 
==2971== by 0x4008AC: main (main.c:46) 
==2971== 
==2971== Use of uninitialised value of size 8 
==2971== at 0x4C2E8C9: __GI_strncmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2971== by 0x4F0B252: _getopt_internal_r (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C240: _getopt_internal (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C2BD: getopt_long (in /usr/lib/libc-2.25.so) 
==2971== by 0x400C3D: getopt_server_parsing (getopt_server_parsing.c:42) 
==2971== by 0x4008AC: main (main.c:46) 
==2971== 
==2971== Invalid read of size 1 
==2971== at 0x4C2E8C9: __GI_strncmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2971== by 0x4F0B252: _getopt_internal_r (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C240: _getopt_internal (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C2BD: getopt_long (in /usr/lib/libc-2.25.so) 
==2971== by 0x400C3D: getopt_server_parsing (getopt_server_parsing.c:42) 
==2971== by 0x4008AC: main (main.c:46) 
==2971== Address 0x1170 is not stack'd, malloc'd or (recently) free'd 
==2971== 
==2971== 
==2971== Process terminating with default action of signal 11 (SIGSEGV): dumping core 
==2971== Access not within mapped region at address 0x1170 
==2971== at 0x4C2E8C9: __GI_strncmp (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==2971== by 0x4F0B252: _getopt_internal_r (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C240: _getopt_internal (in /usr/lib/libc-2.25.so) 
==2971== by 0x4F0C2BD: getopt_long (in /usr/lib/libc-2.25.so) 
==2971== by 0x400C3D: getopt_server_parsing (getopt_server_parsing.c:42) 
==2971== by 0x4008AC: main (main.c:46) 
==2971== If you believe this happened as a result of a stack 
==2971== overflow in your program's main thread (unlikely but 
==2971== possible), you can try to increase the size of the 
==2971== main thread stack using the --main-stacksize= flag. 
==2971== The main thread stack size used in this run was 8388608. 
==2971== 
==2971== HEAP SUMMARY: 
==2971==  in use at exit: 29 bytes in 2 blocks 
==2971== total heap usage: 2 allocs, 0 frees, 29 bytes allocated 
==2971== 
==2971== LEAK SUMMARY: 
==2971== definitely lost: 0 bytes in 0 blocks 
==2971== indirectly lost: 0 bytes in 0 blocks 
==2971==  possibly lost: 0 bytes in 0 blocks 
==2971== still reachable: 29 bytes in 2 blocks 
==2971==   suppressed: 0 bytes in 0 blocks 
==2971== Rerun with --leak-check=full to see details of leaked memory 
==2971== 
==2971== For counts of detected and suppressed errors, rerun with: -v 
==2971== Use --track-origins=yes to see where uninitialised values come from 
==2971== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) 
[1] 2971 segmentation fault (core dumped) valgrind ./zappy_server --h 

Avez-vous une idée de ce qui se passe? C'est ma première utilisation du getopt api, et je suis totalement perdu. Il semble passe du fait que mon opt est préfixé avec - mais je ne sais pas pourquoi ...

voici mon code complet:

static void fill_help_opt(struct option *help_opt) 
{ 
    help_opt->name = "help"; 
    help_opt->has_arg = 0; 
    help_opt->flag = NULL; 
    help_opt->val = 'h'; 
} 

int   getopt_server_parsing(int argc, char **argv, 
          t_server_params *params) 
{ 
    int   get_opt_err; 
    t_opts_checkers opts_fcts[7]; 
    int   idx; 
    struct option  help_opt; 

    fill_opts_fcts(opts_fcts); 
    fill_help_opt(&help_opt); 
    get_opt_err = 0; 
    while ((get_opt_err = getopt_long(argc, argv, "p:x:y:n:c:f:h", 
        &help_opt, NULL)) != -1) 
    { 
     idx = 0; 
     while (idx < 7) 
     { 
      if (opts_fcts[idx].key == get_opt_err 
        && opts_fcts[idx].value(optarg, params, argv) != 0) 
       return (1); 
      ++idx; 
     } 
     if (get_opt_err == '?') 
      return (1); 
    } 
    return (0); 
} 

Je ne wan't coller tout parce que mon école peut trouver ce code et me reprocher d'avoir triché ... (à cause de copier/coller du code, même si c'est le mien).

+0

Veuillez essayer de créer un [Exemple minimal, complet et vérifiable] (http://stackoverflow.com/help/mcve) et nous montrer. Et aussi s'il vous plaît lire [Comment déboguer de petits programmes] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) –

+0

Comment 'help_opt' est-il défini et peuplé? – dbush

+0

help_opt-> name = "aide"; help_opt-> has_arg = 0; help_opt-> flag = NULL; help_opt-> val = 'h'; – Oscar

Répondre

2

Le troisième argument de getopt_long ne doit pas être l'adresse d'un seul struct option, mais un pointeur vers le premier élément d'un tableau de struct option, dont le dernier doit être rempli de zéros. Parce que vous ne passez pas dans un tableau, getopt_long tente de lire passé help_opt comme s'il s'agissait d'un tableau. Cela appelle undefined behavior.

Remplacez help_opt par un tableau avec le dernier élément mis à zéro.

struct option help_opt[] = { 
    { "help", 0, NULL, 'h' }, 
    { NULL, 0, NULL, 0 } 
}; 

... 

while ((get_opt_err = getopt_long(argc, argv, "p:x:y:n:c:f:h", 
       help_opt, NULL)) != -1) 
+0

Oui, désolé, il suffit de lire le bon document et je n'ai pas compris cette ligne "Le dernier élément du tableau doit être rempli de zéros." – Oscar