对于学校项目我必须使用getopt_long()或getopt_long_only()。这是我的循环:
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);
}
我不想粘贴所有东西,因为我的学校可以找到这些代码并责怪我作弊......(因为复制/粘贴代码,即使它是我的代码)。
答案 0 :(得分: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)