【问题标题】:Why segmentation fault using atoi command line arguments为什么使用 atoi 命令行参数出现分段错误
【发布时间】:2015-09-18 11:13:39
【问题描述】:

我需要传递两个命令行参数,我尝试了以下方法:

#include <stdio.h>
#include <stdlib.h>

void power(int base, int exp){

    int res=1;

    while(exp!=0){
       res *= base;
        --exp;
    }

    printf("Res = %d",res);
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
        exit(1);
    }else{
        power(atoi(argv[1]),atoi(argv[2]));
    }

    printf("\n");
    return 0;
}

输出:

michi@michi-laptop:~$ ./power
Usage ./power arg2 arg2
(EG: ./power 2 3)
michi@michi-laptop:~$ ./power 2 3
Res = 8

直到这里一切正常,但是如果将 argv[1]argv[2] 保存在这样的变量中:

int base = atoi(argv[1]);
int exp = atoi(argv[2]);

我得到分段错误

代码:

#include <stdio.h>
#include <stdlib.h>

void power(int base, int exp){

    int res=1;

    while(exp!=0){
       res *= base;
        --exp;
    }

    printf("Res = %d",res);
}

int main(int argc, char *argv[]) {

    int base = atoi(argv[1]);
    int exp = atoi(argv[2]);

    if (argc != 3) {
        printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
        exit(1);
    }else{
        power(base, exp);
    }

    printf("\n");
    return 0;
}

但是当我在 printf 中使用 Atoi 时,一切正常:

#include <stdio.h>
#include <stdlib.h>

void power(int base, int exp){

    int res=1;

    while(exp!=0){
       res *= base;
        --exp;
    }

    printf("Res = %d",res);
}

int main(int argc, char *argv[]) {

    if (argc != 3) {
        printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
        exit(1);
    }else{
        power(atoi(argv[1]), atoi(argv[2]));
    }

    printf("\n");
    return 0;
}

我的问题是:

这个问题是因为 Atoi 造成的吗?

出现这个问题是因为我尝试访问 argv[1]argv[2] 并且当我键入 ./program?

如果我输入 ./program 2 3 一切正常,这让我认为发生分段错误是因为我尝试访问当时不属于我的内存位置。

【问题讨论】:

  • @amdixon 先生,void power() 究竟是如何返回整数的?
  • 因不正确而被删除。
  • "这个问题是不是因为我尝试访问 argv[1] 和 argv[2] 并且当我键入 ./program 时它们不存在?"是的。你不能使用不存在的数据。
  • @Lundin 谢谢,我有 99% 的把握,这就是问题的原因。

标签: c


【解决方案1】:

这个问题是因为我尝试访问 argv[1] 和 argv[2] 而在我输入 ./program 时它们不存在吗?

是的,问题是您在验证命令行参数是否存在之前尝试访问它们。

在第二个示例代码 sn-p 中,只有在确保输入可用后,才能将值分配给变量 baseexp

int base;
int exp;

if (argc != 3) {
    printf("Usage %s arg2 arg2\n(EG: %s 2 3)\n",argv[0],argv[0]);
    exit(1);
}else{
    /* Assign the values here, as it is verified that arg's are obtained from cmd line*/
    base = atoi(argv[1]);
    exp = atoi(argv[2]);
    power(base, exp);
}

在上面的程序中,确保只有在程序执行时作为命令行参数传递参数(argv[1]argv[2])时才引用它们。

【讨论】:

    【解决方案2】:

    是因为我尝试访问 argv[1] 和 argv[2] 和 当我输入 ./program 时它们不存在?

    这是因为您没有检查 null。如果没有传入参数,argv[1] 和 argv[2] 可能为 null。这会导致分段错误。

    int base = atoi(argv[1]);
    int exp = atoi(argv[2]);
    

    试试这个

    int base = 0;
    int exp  = 0;
    
    if(argv[1] && argv[2])
    {
      int base = atoi(argv[1]);
      int exp = atoi(argv[2]);
    }
    

    或者您可以检查参数计数以确保您有 2 个参数传入。

    if(argc > 2)
    {
      int base = atoi(argv[1]);
      int exp = atoi(argv[2]);
    }
    

    【讨论】:

    • 或者您可以检查 argc 以检查@Santosh 指出的传入了多少参数。
    【解决方案3】:

    当您在没有参数的情况下在argv[ &gt; 0] 上调用atoi 时,您正在访问越界内存,即未定义行为

    根据C Standard的定义,访问越界内存是Undefined Behavior


    您可能会感兴趣

    【讨论】:

    • 为什么 OP 应该让 power() 返回一个 int?除了在方法中打印它之外,他不会尝试在任何地方使用计算值。此外,还有另一个严重的问题——如果第二个条目是负数会发生什么?
    • @FredK 我没看到!我已经习惯了power 函数返回的结果,我认为这个函数也是这样工作的!我的错。感谢您指出。
    猜你喜欢
    • 2020-09-03
    • 2020-09-16
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    相关资源
    最近更新 更多