【问题标题】:Is it possible to repeat getopt是否可以重复getopt
【发布时间】:2013-02-17 06:23:39
【问题描述】:

我正在尝试使用内置命令创建一个基本的 shell,但我遇到了一些关于 getopt 的问题。这是输出(使用 valgrind):

$ mkdir -p foo/bar
mkdir
-p
foo/bar
FLAGON
$ mkdir -p foo/test
mkdir
-p
foo/test
==15377== Invalid read of size 1
==15377==    at 0x5201BBE: _getopt_internal_r (in /usr/lib/libc-2.17.so)
==15377==    by 0x5202CEA: _getopt_internal (in /usr/lib/libc-2.17.so)
==15377==    by 0x5202D37: getopt (in /usr/lib/libc-2.17.so)
==15377==    by 0x40351A: shell_ns_cmd_mkdir (shell.c:542)
==15377==    by 0x403AB4: normal_shell_cb (shell.c:610)
==15377==    by 0x402E8E: shell_mainloop (shell.c:402)
==15377==    by 0x401B67: main (main.c:52)
==15377==  Address 0x54e0912 is 2 bytes inside a block of size 3 free'd
==15377==    at 0x4C2AD3C: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==15377==    by 0x402C93: shell_mainloop (shell.c:384)
==15377==    by 0x401B67: main (main.c:52)
==15377== 
$ 

这里是来源(剪辑):

for (i = 0; i < argc; i++) {
    puts(argv[i]);
}
while ((c = getopt(argc, argv, "p")) != -1) {
    switch (c) {
        case 'p':
            puts("FLAGON");
            mkparents = true;
            break;
        case '?':
            fprintf(stderr, "invalid option -- %c", optopt);
            ret = 127;
            goto end;
            break;
    }
}

所以它第一次运行时 (mkdir -p) 会识别它 (-p) 而第二次运行时则不会。有什么想法吗?

【问题讨论】:

  • 可能是您的标准输出缓冲区由于某种原因第二次没有被刷新?在 puts 之后试试 fflush(stdout)?
  • “它[程序]第一次运行它[程序,或者getopt()?]识别”。 是什么?
  • @Code-Guru,对不起, 和标志一样 (-p)
  • @MiJyn “第二次 it 运行”是什么意思。你的意思是你的程序运行两次还是你的意思是第二次while 循环迭代? (请随时使用这些说明来编辑您的问题。)
  • @Code-Guru,对,这是mkdir 命令(我发布了我的源代码)第二次运行。

标签: c getopt


【解决方案1】:

如果您想扫描多个向量,您需要通过将optind 设置为 1 来重置 getopt

变量 optind 是 argv[] 的下一个元素的索引 要处理的向量。 由系统初始化为1, 并且 getopt() 将在它完成每个元素时更新它 argv[].

如果将 optind 设置为 1 不起作用,请尝试 0,我想我记得在某处读到过。

【讨论】:

  • optind 设置为 1 修复了它,但我仍然收到来自 valgrind 的警告,所以我尝试将其设置为 0,现在它可以正常工作了。谢谢!
  • 请注意,POSIX getopt() 表示:变量optind 是要处理的argv[] 向量的下一个元素的索引。系统应将其初始化为 1,并且getopt() 将在完成argv[] 的每个元素时对其进行更新。如果应用程序在调用getopt() 之前将optind 设置为零,则行为未指定。当argv[] 的元素包含多个选项字符时,未指定getopt() 如何确定哪些选项已被处理。 [...继续...]
  • 如果你读到参数列表的末尾(所以getopt() 返回-1),那么重置optind = 1; 应该重置它以便重新解析。但是,如果你有,为了参数,"abc" 和命令行参数-abc 的选项字符串,并且你尝试在只读ab 后重置解析,你可能没有实现重置——解析可以继续c。 POSIX 明确未指定设置为0;它可能有用也可能没用——你必须阅读你的实现手册,或者进行实验,并希望结果在升级过程中保持有效(并担心移植)。
  • 这里是 getopt 的手册页中关于何时将 optind 初始化为 0 的内容: 注意 扫描多个参数向量或多次重新扫描同一向量并希望使用 GNU 的程序诸如 optstring 开头的 '+' 和 '-' 之类的扩展,或在扫描之间更改 POSIXLY_CORRECT 的值,必须通过将 optind 重置为 0 来初始化 getopt(),而不是传统的值 1。(重置为 0 会强制调用重新检查 POSIXLY_CORRECT 并检查 GNU 扩展的内部初始化例程
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-03
  • 2015-04-25
  • 2020-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多