为什么使用atoi命令行参数会导致分段错误

3

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

#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() 如何返回整数? - Michi
removed as incorrect. - amdixon
2
“这个问题是因为我尝试访问 argv[1] 和 argv[2],但当我输入 ./program 时它们不存在吗?” 是的。你不能操作不存在的数据。 - Lundin
@Lundin 谢谢,我99%确定那就是原因,所以才问的。 - Michi
3个回答

4
这个问题是因为你试图访问 argv[1] 和 argv[2],但在输入 ./program 时它们不存在。在第二个示例代码片段中,问题在于你没有先验证命令行参数是否存在就尝试访问它们。
请确保输入可用后,再将值分配给变量 base 和 exp。
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

这个问题是由于当我输入./program时,尝试访问argv [1]和argv [2],但它们不存在吗?

这是因为您没有检查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]);
}

或者你可以像@Santosh指出的那样检查argc来检查传递了多少个参数。 - Vivek Vijayan

1

为什么OP应该让power()返回一个int?除了在方法内部打印它之外,他没有尝试在任何地方使用计算出的值。此外,还有另一个严重的问题 - 如果第二个输入是负数会发生什么? - FredK
@FredK 我没注意到!我太习惯于power函数返回结果了,所以我假设这个也是这样工作的!我的错。谢谢你指出来。 - Enzo Ferber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接