繁体   English   中英

C程序给我分段错误11

[英]C Program gives me segmentation fault 11

因此,我认为问题在于将ref数组中的参考号作为字符串获取,并将其转换为整数,然后转换为复制到页面数组的整数数组结果。 由于我遇到了分段错误11,所以我要遍历数组的边界。 只是不确定如何解决此问题。

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


int main()
{

  char ref[30];// array that holds reference string
  int frame_size;// maximum number of frames is 8
  // a frame holds a number thats in the reference stream.  
  int optimal_fault =0;
  int lru_fault =0;// least recently used faults
  int mfu_fault =0;// most frequently used faults
  int lfu_fault =0;// least frequently used faults    
  int pages = 0;//counts how many times you've looped
  //int page=0;//this will be the pages array 
  printf(" Please enter reference string: ");


  fgets(ref, 30, stdin);
  int num;

  //printf("reference: %c", &ref);
  printf(" Please enter the number of frames(no more than 8 allowed)\n");

  scanf("%d",&frame_size);

  int len = strlen(ref);
  int results[len];
  int page[len];
  int k=0;


  printf("len: %d:",len);
  for(int i=0; ref[i]!= '\0'; i++)
  { 
    if(isdigit(ref[i]))
    {
      num = sscanf(&ref[i], "%d", &results[i]);
      printf("results: %d\n", results[i]);
      page[k] = results[i];
      printf("page: %d\n", page[k]);
      k++;
      i++;
    }

  }
  return 0;
 }

我很乐意解决您的程序所遇到的问题,但是您需要有开放的胸怀,并愿意尝试解决我提出的问题。 我将找出错误。 您进行了明显的更改,并进行了测试。 几乎可以肯定,您的错误会在此过程中消失。 如果他们不这样做,请使用您所做的更改发布问题的更新并ping通我,我们将从那里开始工作...


首先,让我们考虑一下在提供类似"0"的字符串时如何执行。

预计i将为该字符串增加一次,因为其中只有一个字符,因此循环如下所示: for(int i=0; ref[i]!= '\\0'; i++) .. 。没有理由相信这段代码将使i一次增加一次,对吗?

但是,您的代码在这里再次增加:

if(isdigit(ref[i]))
{
  /* SNIP */
  i++;    // <--- ERROR HERE!
}

您的代码跳过了以字符串结尾的'\\0'字节,因为它增加了太多次。 它从数组末尾跳出,调用未定义的行为。 期望这可能会导致段错误是现实的,但是由于它是UB,所以没有要求。


isdigit希望其参数为unsigned charEOF 任何不是EOF负值都可能导致断言错误 也许您打算写: if(isdigit((unsigned char)ref[i]))


int len = strlen(ref);
int results[len];
int page[len];

首先, strlen返回size_t 如果源值超出目标类型的范围,则从无符号到有符号整数类型的转换将导致实现定义的行为。 该实现定义的行为可能(理论上)可能包含陷阱表示,这可能会引发陷阱(即段错误)。

此外,您是否考虑过当len为0(例如,您有一个空字符串)时,您声明的数组大小为0? 根据C标准,这是未定义的行为。

...每次评估时,其值都应大于零。

也许您打算写这样的东西:

size_t len = strlen(ref);
if (len == 0) {
    puts("ref is too small! This field must be at least one byte...");
    return 0;
}
int results[len];
int page[len];
printf("len: %zu:",len); // NOTE: %zu causes printf to print a size_t; don't use %d for that.

考虑将size_t用于表示大小的其他变量,例如ik ,因为int可能会环绕为负值(这是行为不确定的结果,从技术上讲,它可能崩溃或恶化)。 您不想results[i] i为负数的结果,对吗? (在此代码中, ref不能有那么多字节)


int main()在标准C中不是有效的入口点。您应该使用int main(void) ,它指定主入口点不带参数,这与您使用的指定主入口点采用的参数不同。未指定数量的未指定类型的参数。 该错误有时会导致段错误,可以通过编译以下两个程序来演示该错误:

int main() {
    main(42, "hello", -1.0); // WHAT?! main() can accept three arguments?!
}

int main(void) {
    main(42, "hello", -1.0); // Note the compiler error...
}

再说一次,这是UB,所以没有任何要求...不幸的是,在我花了十分钟的搜索时间之后,我找不到任何链接,但是,我确定在程序终止时,我已经看到了一个导致段错误的实例。


您(几乎)应该始终检查scanf的返回值。 scanf("%d",&frame_size); 不能保证成功,因此不能保证frame_size包含一个合理的值。 话虽如此,在这里似乎没有在任何逻辑中使用frame_size 如果您需要从stdin读取并丢弃一个int值,则可以使用scanf("%*d"); 那是唯一(最有可能)您不需要检查返回值的情况。

这也适用于sscanf 我注意到您在这里保存sscanf的返回值: num = sscanf(&ref[i], "%d", &results[i]); ...但是,您什么也没做! 结果,您不能保证results[i]包含合理的值。 真可惜...

num = sscanf(&ref[i], "%d", &results[i]);
if (num != 1) {
    continue;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM