【问题标题】:Segmentation Fault with argv when adding an extra argument添加额外参数时出现 argv 的分段错误
【发布时间】:2020-03-06 23:01:05
【问题描述】:

我有一个代码可以测试命令是否与正确的参数一起使用,如果是,则通过调用另一个函数将其附加到文件中。

下面是代码:

void main(int argc, char *argv[]){
        char accnum[10];
        char fname[30];
        char lname[30];
        char date[10];
        int amt;
        FILE *q = fopen("bankdata.csv","r");
        if(!q){
                fprintf(stderr,"Error, unable to locate the data file bankdata.csv");
                exit(100);
        }
        if(argc == 1 ){
                 fprintf(stderr,"Error, incorrect usage!\n");
                 fprintf(stderr,"-a ACCTNUM NAME\n");
                 exit(1);
        }
        if(strcmp(argv[1],"-a") == 0){
                if(argc < 4){
                        fprintf(stderr,"Error, incorrect usage!\n");
                        fprintf(stderr,"-a ACCTNUM NAME\n");
                        exit(1);
                }else if(argc > 3){
                        if((sscanf(argv[2], "%s", accnum ) == 1 ) &&
                           (sscanf(argv[3], "%s", fname ) == 1) &&
                           /*(sscanf(argv[4], "%s", lname ) == 1)*/){ //commented out
                                add(accnum,fname/*,lname*/);
                        }
                }
         }
}
void add(char accnum[], char fname[]/*, char lname[]*/){
//      printf("%s, %s, %s", accnum, fname, lname);
        size_t line = 0;
        char buf[100] = "";
        char *term = accnum;
        FILE *fp = fopen ("bankdata.csv", "a+");
        while (fgets (buf, 100, fp)) {     /* read each line */
                if (strstr (buf, term)) {       /* test for term  */
                        fprintf(stderr,"Error, account number %s already exists\n", accnum);
                        fclose(fp);
                        exit(50);
                }
                if (strchr (buf, '\n')) line++; /* increment line */
        }
        fprintf(fp,"AC,%s,%s",accnum,fname);
        fclose(fp);
}


这样当我进入时

./a.out -a 1111 Joe Blow

它附加到另一个文件

Ac,1111,Joe

问题是,当我尝试添加姓氏(即uncomment &amp;&amp; (sscanf(argv[4], "%s", lname ) == 1)))并使用相同的命令行(./a.out -a 1111 Joe Blow)时,它给了我一个分段错误,我不知道为什么。我还尝试取消注释添加功能中的所有相关部分,但它不会改变任何东西。

我认为这与 argv[4] 为空有关,因为这是我之前编写代码时遇到的问题之一,但是 argv[4] 应该是“吹”吧?

任何帮助表示赞赏。

【问题讨论】:

  • 要使argv[4] 不为空,argc 必须大于 4,而不是大于 3。您是否修改了 fprintf(fp,"AC,%s,%s",accnum,fname); 以发出 lname?也无需像您一样复制argv[ n ] - 只需将参数直接传递给您的add() 函数:add( argv[2], argv[3],...)。如果用户输入过长的字符串,你现在所做的很容易出现各种问题。
  • char *argv[] 是一个 指针数组,指向保存参数的以 nul 结尾的字符串。最后一个参数之后的下一个指针是NULL(一个sentinel NULL)。 ./a.out -a 1111 Joe Blow 中有多少个参数,其中 ./a.out 是第一个参数 (argv[0]),"Blow" 是最后一个参数 argv[4]
  • 你为什么使用,例如sscanf(argv[2], "%s", accnum ) 什么时候可以简单地以add (argv[2], argv[3], argv[4]); 进行函数调用,而不必重复存储已经是每个程序参数的内容?
  • 该代码应该会给您一堆警告,除非您禁用它们,因为缺少各种标准标头的包含。我猜你的真实代码有它们,但是你的问题缺少minimal reproducible example

标签: c segmentation-fault


【解决方案1】:

你可以稍微简化一下。

由于您使用固定数量的需要存在的参数, 先检查是否足够

if (argc != 5) 
{
  puts("incorrect number of arguments, syntax: {switch} {accountnumber} {firstname} {lastname}");
  return -1;
}

参数数量现在是正确的,继续用开关检查开关,但首先要确保开关字符串足够长

if (strlen(argv[2])<2)
{
  puts("switch must be at least two characters long e.g. -a");
  return -2;
}

switch( argv[2][1] )
{
  case 'a':
    add(argv[3],argv[4], argv[5]);  
    break;
  default:
    printf("unrecognized switch %s", argv[2]);
    break;
}  


void add(char* accnum, char* fname, char* lname)
{
  // check arguments for safety
  if (accnum == NULL || fname == NULL || lname == NULL)
  {
    puts("invalid arguments passed to add");
    return;
  }
 ...

也许可以对参数添加更多检查,例如它是否是有效的帐号等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-19
    • 2020-12-08
    • 2020-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多