数组存储400万项斐波那契偶数和程序崩溃,求修复方案
你的程序崩溃的核心原因是栈溢出(Stack Overflow),跟数组的使用方式直接相关,下面给你详细拆解并提供修复方案:
为什么数组会导致崩溃?
你在main函数里声明了int a[4000000]——这个数组是分配在栈内存上的。栈内存的空间非常有限:Windows系统默认栈大小通常只有1MB,Linux一般是8MB左右。而400万个int元素(每个int占4字节)总大小是16MB,远远超出了栈的承载上限,程序运行时会直接因为栈空间耗尽而崩溃。
当你把数组大小改成10时,总大小只有40字节,完全在栈的承受范围内,所以能正常运行。哪怕你改成unsigned long long类型,每个元素占8字节,400万元素总大小是32MB,只会让栈溢出更严重,自然还是崩溃。
修复方案
方案1:改用堆内存分配大数组
堆内存的空间远大于栈,适合存储大尺寸的数据。我们可以用malloc在堆上分配数组,用完后记得用free释放内存:
#include <stdio.h> #include <stdlib.h> int main() { // 在堆上分配数组,同时检查分配是否成功 unsigned long long *a = malloc(4000000 * sizeof(unsigned long long)); if (a == NULL) { printf("内存分配失败!\n"); return 1; } unsigned long long sum = 0; int i; for(i = 0; i < 4000000; i++) { if(i == 0) { a[0] = 1; } else if(i == 1) { a[1] = 2; } else { a[i] = a[i-1] + a[i-2]; // 新增溢出检查:斐波那契增长极快,unsigned long long也会很快溢出 if(a[i] < a[i-1]) { printf("数值溢出,提前终止循环\n"); break; } } if(a[i] % 2 == 0) { sum += a[i]; } } printf("sum=%llu\n", sum); // 必须释放堆内存,避免内存泄漏 free(a); return 0; }
方案2:优化算法,完全抛弃数组
其实计算斐波那契数列的偶数项和,根本不需要存储所有项——你只需要跟踪当前项和前两项的值就行,这样内存占用几乎为0,效率还更高。参考你找到的无数组代码,我调整成适配你需求的版本:
#include <stdio.h> int main() { unsigned long long prev_prev = 1; // 第1项 unsigned long long prev = 2; // 第2项 unsigned long long sum = 2; // 初始prev是偶数,先计入总和 unsigned long long current; // 注意:斐波那契数列增长极快,unsigned long long大概到第90项就会溢出 // 如果你的需求是计算"不超过400万"的偶数项和,建议把循环条件改成 current <= 4000000 for(int i = 2; i < 4000000; i++) { current = prev_prev + prev; // 溢出检查,避免无效计算 if(current < prev) { printf("数值溢出,提前终止\n"); break; } if(current % 2 == 0) { sum += current; } // 更新前两项的值 prev_prev = prev; prev = current; } printf("sum=%llu\n", sum); return 0; }
额外提醒
斐波那契数列的数值增长速度是指数级的,哪怕用unsigned long long(最大能存到18446744073709551615),也只能计算到第90项左右就会溢出。所以你的循环跑400万次完全没有意义——前100次循环后数值就已经溢出变成错误值了。如果你的需求是计算不超过400万的斐波那契偶数项和,记得把循环条件改成判断current <= 4000000,而不是固定循环400万次。
内容的提问来源于stack exchange,提问作者keerthe_k

