c - 为什么这个递归代码会抛出段错误?

标签 c recursion segmentation-fault

当我运行以下用 gcc 编译的代码(唯一打开的选项是 -std=c99)并运行可执行文件时,我得到一个段错误(msg核心转储)。

这是为什么?

#include <stdio.h>

int count_factors(int n, int i) {
    int m = n;
    if (m == i) {
        return 1;
    } else if (m % i == 0) {
        while (m % i == 0) m = m / i;
        return 1 + count_factors(m, i);
    } else {
        return count_factors(m, i+1);
    }
}

int main() {

    int streak_size = 4;
    int streak = 0;
    int solution = 0;
    int n = 2;

    while (solution == 0) {
        n += 1;
        int c = count_factors(n, 2);
        if (c == streak_size) {                  
            streak += 1;
        } else {
            streak = 0;
        }
        if (streak == streak_size) solution = n;
    }
    printf("%i", solution);
    return 0;
}

最佳答案

在您的递归中,您正在考虑一种基本情况。但是,有两个:

  • m == i:当只有 1 个最大因子时会出现这种情况
  • m == 1:当有多个最大因子时会发生这种情况

您将在 m=4n=2 上进入无限循环,因为您错过了第二种情况。此处,if (m % i == 0) 为真,因此 while (m % i == 0) m = m/i; 运行。由于 4 是 2 的倍数,因此当 m 为 1 时,此循环将结束。

当你再次递归时,你有 m=1n=2。这将命中 else 子句,您可以在其中使用 m=1n=3 再次调用 count_factors。这一直持续到堆栈爆炸。

添加第二个基本情况将修复无限递归:

int count_factors(int n, int i) {
    int m = n;
    if (m == i) {
        return 1;
    } else if (m == 1) {
        return 0;
    } else if (m % i == 0) {
        while (m % i == 0) m = m / i;
        return 1 + count_factors(m, i);
    } else {
        return count_factors(m, i+1);
    }
}

实际上,您可以去掉第一种情况,因为它只是 if (m % i == 0) 的一个特例:

int count_factors(int n, int i) {
    int m = n;
    if (m == 1) {
        return 0;
    } else if (m % i == 0) {
        while (m % i == 0) m = m / i;
        return 1 + count_factors(m, i);
    } else {
        return count_factors(m, i+1);
    }
}

然后程序运行完成,输出 134046。

编辑:

如果没有递归,它会运行得更快:

int count_factors(int n, int i) {
    int m = n;
    int total = 0;
    while (m != 1) {
        if (m % i == 0) {
            while (m % i == 0) m = m / i;
            total++;
        }
        i++;
    }
    return total;
}

在我的机器上,递归版本大约需要 9 秒。迭代版本大约需要 3 秒。

关于c - 为什么这个递归代码会抛出段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33502990/

相关文章:

http - Angular 2 : Recursion with Callbacks and REST api calls

c - 用 C 写入文件时出现段错误

javascript - 了解如何在 vanilla JavaScript 中实现 lodash 的 _.flowRight

javascript - 如何使用事件驱动模型 "keep trying until it works"?

c-尝试添加到 Struct 中的 char 数组时出现段错误

optimization - 如果我启用 C 优化 -O2 或 -fstrict-overflow(-O1 很好),我的 C 程序会崩溃

c - 读取 proc 文件时权限被拒绝错误

c - 什么是 alloc.h?

c - 格式化二进制数字,每组 4 位数字之间有空格

C字符串嵌套拆分