[英]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 char
或EOF
; 任何不是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
用于表示大小的其他变量,例如i
和k
,因为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.