计算质数的C程序在maxCheck超过50万时触发段错误
你的问题根源非常明确:栈溢出(Stack Overflow),和整数溢出完全无关——50万远小于INT_MAX(2147483647),完全不用担心超出int的取值范围。
为什么会出现段错误?
你在main函数里声明的previousPrimes是栈上的局部数组:
int previousPrimes[maxCheck];
栈是操作系统为每个线程分配的小块内存,通常只有几MB到十几MB(比如Linux默认栈大小一般为8MB)。当maxCheck达到50万时,这个数组的大小是500000 * sizeof(int),也就是2000000字节(约2MB),看起来还在栈的范围内,但如果maxCheck继续增大(比如100万就是4MB),再加上栈上其他变量、函数调用栈帧的开销,很快就会耗尽栈空间,触发段错误,或者因为栈被破坏导致程序执行流程混乱,出现无响应的情况。
而堆(Heap)的内存空间几乎等同于系统的可用内存,静态存储区的空间也远大于栈,这两个区域才适合存放大型数组。
解决方案
方案1:动态内存分配(推荐)
在堆上用malloc分配数组,用完记得用free释放内存,这是最灵活的方案,能支持极大的maxCheck:
int main(int argc,char *argv[]) { int i; // 动态分配堆内存,检查分配是否成功 int *previousPrimes = malloc(maxCheck * sizeof(int)); if (previousPrimes == NULL) { perror("Failed to allocate memory"); return 1; } currentNumPrimes = 0; // 确保计数变量初始化(如果之前未做) for (int i = 2; i < (maxCheck + 1); i++) { if (checkForPrime(i, previousPrimes)) { previousPrimes[currentNumPrimes] = i; currentNumPrimes++; printf("%s%d Is Prime\n", green, i); } else { printf("%s%d Is Not Prime\n", cyan, i); } } printf("\n%s%f percent of numbers checked were prime", normal, ((double)currentNumPrimes / (double)maxCheck * 100)); // 释放堆内存,避免内存泄漏 free(previousPrimes); return 0; }
方案2:将数组声明为静态
静态数组会被分配到静态存储区(而非栈上),静态存储区的空间远大于栈:
int main(int argc,char *argv[]) { int i; static int previousPrimes[maxCheck]; // 加static关键字 // 后续逻辑与原代码一致... }
不过静态变量的生命周期是整个程序运行期间,若maxCheck是极端大的数值,静态存储区也可能不够用,因此动态分配仍是更优选择。
其他小建议
优化全局变量的使用:你的
currentNumPrimes看起来是全局变量,虽然能正常工作,但建议改成通过参数传递给checkForPrime函数,让代码更模块化、可维护:int checkForPrime(int num, int previousPrimes[], int currentNumPrimes) { int i; for (i = 0; i < currentNumPrimes; i++) { if (num % previousPrimes[i] == 0) { return 0; } } return 1; }调用时修改为:
if (checkForPrime(i, previousPrimes, currentNumPrimes))关于数组初始化:你提到没有初始化数组,这在你的逻辑里是完全没问题的——只有
currentNumPrimes之前的元素会被赋值和访问,后续未初始化的元素不会被用到,因此初始化与否不影响功能。
总结
你的质数判断逻辑是完全可行的,问题仅出在大型数组的存储位置上:栈空间太小,无法容纳几十万元素的数组。换成堆分配或静态数组就能彻底解决这个问题,让程序支持更大的maxCheck。
备注:内容来源于stack exchange,提问作者Gbotdays

