【问题标题】:C - Segmentation Fault (core dumped)C - 分段错误(核心转储)
【发布时间】:2016-09-17 13:01:12
【问题描述】:

我正在尝试编写一个简单的 C 程序,该程序接受一个数字的输入并返回数字的数字之和以及数字的倒数。该程序目前不完整,因为我在测试时不断遇到 Segmentation Fault 错误。

代码如下:

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

int sumdigits(int);

int main() {
    int num;                // The number to be read
    int reverse;            // The reverse of the input
    int sum;                // The sum of the digits


    printf("Enter a number: ");
    scanf("%d", &num);
    sum = sumdigits(num);
    printf("Sum of digits: %s", sum);
}

int sumdigits(int number) {
    int sum = 0;
    int temp = number;
    while (temp != 0) {
        sum += (temp % 10);
        temp /= 10;
    }
    return sum;
}

通过使用一些打印语句,我发现错误很可能发生在以下几行中:

printf("Enter a number: ");
scanf("%d", &num);

我可以输入一个数字,但紧接着我收到一条消息说分段错误(核心转储)并且程序退出。以 sudo 权限运行程序只会提供分段错误,而没有消息的“核心转储”部分。

here 后面的指令提供的调试信息似乎表明 printf 语句是导致错误的原因,因为这是输出:

(gdb) run
Starting program: /home/sschmalz/Documents/Classes/CIS308/proj1/debug 
Enter a number: 123

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a62fb4 in vfprintf () from /lib64/libc.so.6

但是,我不知道如何处理这些信息,因此无法解决错误。

我已就实验室中的同样错误向我的教授寻求帮助,但他无法找到解决方案。这已经发生在两个不同的实验室,加上这个项目,这让我觉得这可能与我的计算机设置有关,而不是与代码本身有关。

我正在使用 vim 编写程序并使用 gcc 进行编译。在大多数情况下,我不会重命名编译器的输出,所以我使用“./a.out”运行它。我使用 Fedora 24 编写和运行这些程序。如果需要有关我的系统的任何其他信息,请告诉我。

【问题讨论】:

  • 通过%s 转换将int 传递给printf() 的未定义行为。
  • 我计算机上的编译器由于某种原因没有捕获字符串格式错误。我将文件上传到我大学的 Linux 服务器并在那里编译它,这给了我异常和修复。谢谢大家的帮助,这么小的问题我都觉得自己是个白痴。

标签: c segmentation-fault runtime-error


【解决方案1】:

改变

printf("Sum of digits: %s", sum);

printf("Sum of digits: %d", sum);

%s 用于字符串而非整数(%d 用于有符号整数)。

http://www.cplusplus.com/reference/cstdio/printf/

【讨论】:

  • 感谢您指出这一点。由于某种原因,我计算机上的编译器没有捕捉到这个,但是当我将它上传到我大学的 Linux 服务器并编译时,它抛出了一个异常。
  • @SamSchmalzried 这通常不会被捕获,因为所有编译器都需要知道或关心的是printf() 采用任意字符串和一组可变参数(因此必然是任意的)参数,这两个你都提供了。检查您提供的参数组合是否有意义将需要大量杂技 - 并且可能需要对可变参数 idk 进行运行时检测 - 大多数编译器不会浪费时间,除非您明确告诉他们这样做。否则,他们只是假设你的论点是有道理的。
【解决方案2】:

你在printf()函数中使用了错误的格式说明符,修改为:

printf("Sum of digits: %d", sum);

它会正常工作(%d 代表十进制(数字),%s 代表字符串)。

【讨论】:

    【解决方案3】:

    我运行了您的代码,它可以工作,但您必须将 printf("Sum of digits: %s", sum); 更改为 printf("Sum of digits: %i", sum);printf("Sum of digits: %d", sum);

    printf() 中使用%d%i 没有区别,因为:

    1. 转换说明符及其含义为: d,i - int 参数转换为样式 [−]dddd 的有符号十进制。这 精度指定出现的最小位数;如果 被转换的值可以用更少的数字表示,它是 用前导零扩展。默认精度为 1。 以零精度转换零值是没有字符的。 来源:C99标准http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

    但是,在scanf() 中使用%d%i 时会有所不同,因为前者存储为十进制整数,而后者存储为整数。来源:https://cs50.harvard.edu/resources/cppreference.com/stdio/scanf.html

    我运行的代码有效:

    #include <stdio.h>
    #include <string.h>
    
    int sumdigits(int);
    
    int main() {
        int num;                // The number to be read
        int reverse;            // The reverse of the input
        int sum;                // The sum of the digits
    
    
        printf("Enter a number: ");
        scanf("%i", &num);
        sum = sumdigits(num);
        printf("Sum of digits: %i", sum);
    }
    
    int sumdigits(int number) {
        int sum = 0;
        int temp = number;
        while (temp != 0) {
            sum += (temp % 10);
            temp /= 10;
        }
        return sum;
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-14
      • 2017-02-25
      • 2016-07-12
      • 2018-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多