【问题标题】:C Prime Number crashes at 64901 [closed]C质数在64901崩溃[关闭]
【发布时间】:2017-11-24 21:50:48
【问题描述】:
#include <stdio.h>
#include <stdlib.h>
#define size 20000000

int prim[size];
int  i, zahl, zaehler, erg;


int sieve(int zahl, int prim[], int zaehler) {
    if(zahl == 2000000)
        return 1;

    for(i=0; i<=zaehler; i++) {
        erg = zahl%prim[i];

        if(erg==0) {
            zahl++;
            return sieve(zahl, prim, zaehler);
        }   
    }           

    zaehler++;
    prim[zaehler]=zahl;
    zahl++;
    printf("%d\n", prim[zaehler]);
    return sieve(zahl, prim, zaehler);      
}

int main(){

    zaehler = 0;
    zahl = 2;       

    for(i=0;i<size;i++)
        prim[i]=2;

    sieve(zahl, prim, zaehler);
}

当我试图计算素数时,当我运行这段代码时,它总是在数字 64901 处崩溃。 可能是什么问题?

【问题讨论】:

  • 欢迎来到 SO。这是您学习如何调试自己的程序的绝佳机会。与其他人发现你的错误相比,你会从中学到更多。
  • “它总是在数字 64901 处崩溃”并没有多大用处来描述您所看到的错误。它是否说“错误#so-and-so”? “分段故障”?它只是停止就好像它运行成功了吗?等
  • 如果你有一个 1MB 的堆栈大小,你将在大约那个数量的递归之后到达底部。
  • “粉碎”->“崩溃”。 :) 正如博所建议的那样,我怀疑您的堆栈已用完。对于sieve,非递归方法会更好。递归有时很方便,而且有时可能更透明,但如果管理不当,它也会有严重的缺点。
  • 如果你使用Linux,比如说,你可以使用valgrind来调试程序中的内存问题。 valgrind ./myprogram.

标签: c function recursion


【解决方案1】:

具有讽刺意味的是,这实际上是由于递归导致的堆栈溢出。您可以使您的堆栈变大(这只会延迟问题),或者从递归解决方案更改为迭代解决方案。

(无论如何,在这种情况下,一些调试器将无法为您提供帮助。C 初学者在第一次遇到此问题之前很难理解出了什么问题。恭喜!你正在升级 C)

验证它确实是堆栈溢出的一种廉价方法是在递归函数中在堆栈上创建额外的内存,并查看它崩溃的数字是否从 64901 更改。我的猜测是,如果你把 char dummy[2048] 放在那里,它会更快崩溃。

【讨论】:

  • 编译器可能会在优化过程中删除未使用的数组,例如char dummy[2048]。或许建议关闭优化,运行程序建立基线,然后插入虚拟空间,重新运行程序。
  • @EricPostpischil 或者只是 strcpy() 在一些随机数据中。
  • @anonymoose:试图在这些事情上超越编译器是很棘手的。即使您使用strcpy 将一些数据复制到dummy,编译器也可以看到它未被使用并删除dummy 和strcpy,因为它们没有可见的效果(如C 标准中定义的那样)。但是,如果您将 dummy 声明为 volatile char dummy[2048],那么您可以简单地使用 memset 向其写入零,并且编译器将需要实际执行写入操作。
  • 当心超级智能编译器,它们会认为您的整个项目毫无意义,并优化整个项目 /s
  • @TinyTheBrontosaurus:你这孩子,但在某些情况下,你确实需要注意这一点。如果您的程序没有可观察到的行为,那么您可能合法地只得到一个空的main。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 2014-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多