2017-06-21 108 views
0

對於學校項目我必須使用getopt_long()或getopt_long_only()。下面是我的循環:segfault with getopt_long()

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

我在Valgrind的報道一樣,段錯誤:

==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 

你有什麼發生的事情的想法?這是我第一次使用getopt api,而且我完全迷失了。它似乎從事實證明我的選擇是前綴發生的事情 - 但我不知道爲什麼...

這裏是我的全碼:

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); 
} 

我不wan't貼因爲我的學校可以找到這些代碼,並指責我作弊...(因爲複製/粘貼代碼,即使它是我的)。

+0

請嘗試創建一個[最小,完整和可驗證示例](http://stackoverflow.com/help/mcve)並向我們顯示。另請參閱[如何調試小程序](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) –

+0

如何定義和填充'help_opt'? – dbush

+0

help_opt-> name =「help」; help_opt-> has_arg = 0; help_opt-> flag = NULL; help_opt-> val ='h'; – Oscar

回答

2

的第三個參數getopt_long不應該是單個struct option的地址,而是一個指針的struct option陣列,其中最後的應該用零填充的第一個元素。

因爲你沒有傳入數組,所以getopt_long試圖讀取過去的help_opt,就好像它是一個數組。這調用undefined behavior

help_opt更改爲最後一個元素歸零的數組。

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

是的,對不起,只是閱讀正確的文檔,我不理解這一行「數組的最後一個元素必須填充零。」 – Oscar