【问题标题】:Argc returning as 1, argv returning NULL, despite putting in command line arguments尽管输入了命令行参数,但 argc 返回 1,argv 返回 NULL
【发布时间】:2016-06-11 01:10:33
【问题描述】:

我想我对 C 命令行参数有点生疏了。我查看了我的一些旧代码,但不管这个版本是什么,都会出现段错误。

运行方式是 ./foo -n num(其中 num 是用户在命令行中输入的数字)

但不知何故,它不起作用。我哪里错了?

编辑:当我尝试访问 atoi(optarg) 时出现段错误,它是段错误的 atoi(0x0)。

int main(int argc, char *argv[])
{
    int c;
    int maximum_n = max_n(); /* Stores the maximum value in the sequence a long can hold */
    unsigned long *array = NULL;

    while((c = getopt(argc, argv, ":n:")) != -1) {

        switch(c) {
        case 'n':
            if(atoi(optarg) > maximum_n) {
                printf("n is too large -- overflow will occur\n");
                printf("the largest Fibonacci term than can be calculated is %d\n", maximum_n); 
                exit(EXIT_SUCCESS);
            }
            else {
                array = fib_array(atoi(optarg));
            }
            break;
        }   
    }

    printf("The %d Fibonacci term is %lu\n", atoi(optarg), array[atoi(optarg)]);

    return 0;
}

【问题讨论】:

  • argv[0] 是您的第一个参数,通常的 shell 将其设置为可执行文件的基本名称,顺便说一句。
  • 是的,我明白了。这就是为什么我说 argv[1] 是这里的问题,因为它返回 null 但不应该。它应该是用户输入的任何内容。
  • Tyler,你要明白,如果设置了 argv[0],则 argc 为 1。如果设置了 argv[1],则 argc 必须至少为 2。
  • 您的意思可能是:array[atoi(optarg) - 1]。就目前而言,如果您要求第 n 个元素,您实际上得到的是第 (n+1) 个元素。
  • 您没有在任何地方直接访问argvargc。为什么你认为它们有问题?段错误到底在哪里?

标签: c segmentation-fault command-line-arguments argv argc


【解决方案1】:

像许多编程语言一样,C 中的argv[0] 通常包含程序的名称。该值实际上取决于用于启动进程的exec* 系统调用的参数。出于您的目的,那部分无关紧要。需要注意的重要一点是 argc 总是比程序在命令行上接收的参数数量大一。在你的情况下argc == 3argv 的值应该看起来像

argv[0]: "./foo"
argv[1]: "-n"
argv[2]: "10"

您的程序出现段错误的原因是您在 optarg 不再有效后访问它。每次调用getopt() 时,optarg 的值都会发生变化。当您在 while 循环之外调用它时,它已更改为 NULL。当您处于'n' 的开关盒中时,您应该将atoi(optarg) 的值存储到一个变量中。

由于您仍然对此感到困惑,我已经更新了您的代码并进行了必要的修复。

int main(int argc, char *argv[])
{
    int c;
    int maximum_n = max_n(); /* Stores the maximum value in the sequence a long can hold */
    unsigned long *array = NULL;
    int n = -1;

    while((c = getopt(argc, argv, ":n:")) != -1) {

        switch(c) {
        case 'n':
            n = atoi(optarg);
            if(n > maximum_n) {
                printf("n is too large -- overflow will occur\n");
                printf("the largest Fibonacci term than can be calculated is %d\n", maximum_n); 
                exit(EXIT_SUCCESS);
            }
            else {
                array = fib_array(n);
            }
            break;
        }   
    }

    if (n == -1)
    {
        printf("You must specify a value with -n\n");
        return 1;
    }

    printf("The %d Fibonacci term is %lu\n", atoi(optarg), array[n]);

    return 0;
}

【讨论】:

  • 那么,为什么我的代码会出现段错误? argv[0] 很好(这是我的程序的名称),但 argv[1] 是 0x0 而 argv[2] 是乱码。
  • 我看不出你发布的不完整代码有什么问题,所以它一定是你省略的代码或运行它的环境。
  • 确实不是c的问题,而是系统环境的问题。 argv[0] 作为可执行文件的名称是一个约定问题,对于程序员(尤其是安全相关软件)依赖它很重要。当您使用exec* 启动程序时,很容易将 argv[0] 设置为任意值(也可以设置为 NULL 指针)
  • @Ctx 并非所有语言都在标准参数列表中提供可执行文件的名称(或者更确切地说是传递给 exec* 的任何名称)。这就是为什么我在 C 中指定了这种情况。OP 可能用于不同的编程环境。
  • 不,c 包含getopt() 的返回值。你需要保存atoi(optarg)的返回值。
【解决方案2】:

问题出在这里:

 printf("The %d Fibonacci term is %lu\n", atoi(optarg), array[atoi(optarg)]);

当 getopt 没有更多参数要处理时,optarg 设置为 NULL。函数atoi 没有适当的错误检查导致 SIGSEGV。

【讨论】:

    猜你喜欢
    • 2020-01-23
    • 2018-08-05
    • 2020-07-25
    • 2019-05-09
    • 2018-11-30
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多