【问题标题】:why i am getting segmentation fault only when run my code in codechef?为什么只有在 codechef 中运行我的代码时才会出现分段错误?
【发布时间】:2020-10-18 12:54:23
【问题描述】:

这是代码。当我在VS Code 2019 和其他在线编译器中运行代码时,代码运行良好! 但是在 Codechef here 中运行它时,我遇到了一些运行时分段错误错误。

代码

#include<stdio.h>
int main(void)
{
    int T;
    scanf("%d", &T);
    while (T >= 1 && T <= 100)
    {
        char a[10] ;
        int x_counter = 0, y_counter = 0;
        scanf("%s", &a);
        char* ptr = a;
        while (*ptr != '\0')
        {
            if (*ptr == 'x')
                x_counter++;
            else if (*ptr == 'y')
                y_counter++;
            ptr++;
        }
        if (x_counter < y_counter)
        {
            printf("%d\n", x_counter);
        }
        else if (y_counter <= x_counter)
        {
            printf("%d\n", y_counter);
        }
        T--;
    }
    return 0;
}

【问题讨论】:

  • a 有足够的元素吗?此外,您通过传递具有错误类型的 printf() 数据来调用 未定义行为%s 应为 char*,但 char(*)[10] 已传递。应该删除scanf()a 之前的&amp;
  • else if (y_counter &lt;= x_counter) 可以只是 else ,实际上所有 if ... else ... 都可以简化为 printf("%d\n", (x_counter &lt; y_counter) ? x_counter : y_counter); 。使用超出有效范围的值(如 0)初始化 T(错误地以大写形式命名)或检查 scanf("%d", &amp;T) 返回 1 以管理错误输入。将scanf("%s", &amp;a); 替换为scanf("%9s", a);,因为a 的大小为10,并且您还需要放置最后一个空字符,然后再次检查scanf 返回1 以检测EOF 或scanf 之前的错误做*a=0;
  • 我尝试从 scanf() 中删除 & 并将元素数量增加到 1000。但再次显示相同的错误。:(
  • 那么 7000000 个元素呢?问题不是说最大输入大小吗?
  • 修改后的'm'非常有用,要求scanf自行分配正确的缓冲区大小

标签: c segmentation-fault scanf


【解决方案1】:

您的程序将遇到未定义的行为 UB 因为您在 scanf 中的转换说明符 "%s" 需要 char* 但您正在传递 char 指针数组(char**char(*)[])。因此指针参数对于scanf,必须是适合相应转换规范返回的值的类型!!我建议您限制scanf 函数并在每次迭代中刷新stdin 缓冲区,如下所示:

int c;
scanf("%9s", a);
while ((c = fgetc(stdin)) != '\n' && c != EOF); /* Flush stdin */

因为scanf 返回EOF,如果在第一次成功转换或匹配失败发生之前到达输入结尾。如果发生读取错误,也会返回EOF,设置流的错误指示符,并设置errno 来指示错误。 errno&lt;errno.h&gt;头中定义的整型变量,由系统调用和一些库函数设置,在发生错误时指示出错的地方我们可以在下面添加层:

#include <errno.h>
#include <string.h>
....
if(scanf("%9s", a) == EOF)
{
    puts(strerror(errno));
    exit(EXIT_FAILURE);
}
char *strerror(int errnum);

strerror() 函数返回一个指向字符串的指针,该字符串描述 参数errnum中传递的错误码

有关strerrorerrno 的更多详细信息。转到以下链接: errno strerror

【讨论】:

  • scanf() 将自动放置终止空字符,即使达到长度限制也是如此。 example.
  • c 必须是 int。此外,&amp;a 将是 char (*)[10] 类型,并且 在大多数情况下在 scanf 中正常工作,所以这不是原因。
  • @AnttiHaapala - scanf 的指针参数的类型必须适合相应转换规范返回的值。
  • @Adam 是的,否则行为是未定义的,但是在这种情况下它实际上不会导致问题,因为值的表示应该是相同的。
  • @AnttiHaapala - 感谢您的 cmets。您的 cmets 帮助我改进了答案。但是关于 scanf ,我们正在尝试正确编码并遵循 c 标准。所以转述一些实际的事情不是我们可以推荐一些程序员去做的事情。如果你投票我会很高兴:-)
猜你喜欢
  • 2020-12-15
  • 2023-02-08
  • 2022-07-01
  • 2020-11-11
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 2010-10-19
相关资源
最近更新 更多