collatz 函数中的分割错误

Segmentation fault in collatz function

提问人: 提问时间:11/4/2023 最后编辑:pmg 更新时间:11/6/2023 访问量:158

问:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#define max 100000000
int64_t table[max];
int64_t collatz(int64_t a);
int main(int argc,char*argv[])
{
    if (argc !=3)
    {
        printf("ERROR\nUsage: ./collatz {argv1} {argv2}\n");
        return 1;
    }
    int64_t maxlen = 0;
    int64_t num1 = atoi(argv[1]);
    int64_t num2 = atoi(argv[2]);
    if (num1 < 1 || num2 < 1 || num1 > max || num2 > max)
    {
        printf("%"PRId64"\n",maxlen);
        return 2;
    }
    int64_t i;
    for (i=num1;i<=num2;i++)
    {
        int64_t len = collatz(i);
        if (len > maxlen)
        {
            maxlen = len;
        }
    }
    printf("%" PRId64 "\n", maxlen);
    return 0;
}
int64_t collatz(int64_t a)
{
    if (a <= max)
    {
        if(table[a] != 0)
        {
            return table[a];
        }
    }
    int64_t len = 1;
    if (a != 1)
    {
        if (a%2==0)
            len += collatz(a/2);
        else
            len += collatz(a*3+1);
    }
    if (a <= max)
    {
        table[a]=len;
    }
    return len;
}

当我删除 collatz 函数中的最后一个 if 语句时,我出现分段错误。我无法理解这一点,因为数组大小是 100.000.000,而且我从不允许输入大于该值的数字。此外,我知道一个数字可能会超过函数内部的限制,例如 99.999.999,但我很确定高于 100.000.000 的数字永远不会满足函数中的最后一个 if 语句,但是如果我以某种方式删除它,我会得到一个分段错误。

C 函数 分割-故障 拼接

评论

2赞 dimich 11/4/2023
你使用递归,它不是尾递归。编译器无法将其优化为迭代执行,因此使用堆栈。堆栈大小是有限的。
0赞 Chris 11/4/2023
不过,@dimich这不会导致分段错误。
1赞 Fe2O3 11/4/2023
OT:建议。 不要让你的读者眯着眼睛开始计算有多少个零......更好的是,使用#define max (100 * 1000 * 1000)#define max 1e8
1赞 chux - Reinstate Monica 11/4/2023
@Fe2O3 更深:16 位的代码会溢出,32 位会溢出。比 9e15 大得多的整数常数存在不精确的风险。幸运的是,C23 可以根据需要提供 ' 来分离。在这里,如果需要,我将使用并让编译器警告大约 16 位。不要使用 1000 * 1000 * 1000100 * 1000int10 * 1000 * 1000 * 1000int#define max ((size_t)100 * 1000 * 1000size_t
1赞 Fe2O3 11/4/2023
@chux-恢复莫妮卡:你指出这一点很好。对于粗心大意的人(像我一样)来说,这是一个陷阱,特别是随着越来越多的位被普遍使用。

答:

0赞 Chris 11/4/2023 #1

在函数中,你有一个大小的数组。这意味着最大有效索引为 。但是,您测试它小于或等于 。这允许越界阵列访问,并且可能导致分段错误。collatztablemaxmax - 1amax

    if (a <= max)
    {
        if(table[a] != 0)
        {
            return table[a];
        }
    }