C语言求≤N素数和程序部分输入下异常终止,求排查帮助
问题排查与修复方案
我来帮你梳理这个素数求和程序的问题,它出现随机运行时错误主要是这几个核心原因,咱们逐个解决:
1. 内存分配的边界与合法性问题
当输入的n是0或者1时,malloc(sizeof(int)*n)会分配0字节内存,这时候去访问a[0]或a[1]属于非法内存操作,直接触发崩溃。另外,n是long long类型,但malloc的参数是size_t,如果n大到让sizeof(int)*n溢出(比如n超过SIZE_MAX / sizeof(int)),会导致实际分配的内存远小于需求,后续访问数组元素时必然越界。
修复方式:
- 先判断
n的大小,若n < 2直接输出0(小于2的数没有素数),跳过数组相关逻辑; - 转换
n为size_t类型再分配内存,同时检查malloc的返回值,避免分配失败导致的崩溃:
if (n < 2) { printf("0\n"); continue; } size_t arr_size = (size_t)n + 1; // 提前预留n+1的空间,解决后续索引问题 int *a = malloc(sizeof(int) * arr_size); if (a == NULL) { fprintf(stderr, "内存分配失败\n"); exit(EXIT_FAILURE); }
2. 数组索引越界
你分配的数组大小是n,但循环里for(i=2; i<=n; i++)会访问a[i]——数组的合法索引是0到n-1,a[n]属于越界访问,这是典型的未定义行为,会随机触发运行时错误。
修复方式:
把数组分配大小改成n+1,让索引0到n都能被合法访问(上面的修复代码已经包含这一步)。
3. 整数溢出导致的逻辑混乱
i和j都是int类型,当n很大时,i*j会超出int的取值范围发生溢出,溢出后i*j会变成负数,导致i*j <= n的条件一直成立,内层循环无限执行,或者访问数组的非法索引引发崩溃。
修复方式:
把i、j、t都改成long long类型,避免乘法溢出:
long long j,i,t;
4. 内存泄漏问题
每次循环里malloc的内存没有用free释放,多次测试后会耗尽系统内存,导致后续malloc失败甚至程序崩溃。
修复方式:
在每次循环末尾,打印完结果后释放内存:
printf("%lld\n",sum); sum=0; free(a); // 释放当前循环分配的内存
完整修复后的代码
#include<stdio.h> #include<stdlib.h> int main() { long long j,i,t; long long int n, sum=0; scanf("%lld",&t); while(t--) { scanf("%lld",&n); if (n < 2) { printf("0\n"); continue; } int *a = malloc(sizeof(int) * (n + 1)); if (a == NULL) { fprintf(stderr, "内存分配失败\n"); exit(EXIT_FAILURE); } a[0] = 0; a[1] = 0; for(i=2; i<=n; i++) { a[i] = i; } for(i=2; i<=n; i++) { if (a[i] == 0) continue; // 跳过已标记的非素数,优化效率 for(j=2; i*j<=n; j++) { a[i*j] = 0; } sum += a[i]; } printf("%lld\n",sum); sum=0; free(a); } return 0; }
我还加了个小优化:在内层循环前判断a[i]是否为0,已经被标记为非素数的数直接跳过,能减少不必要的循环,提升程序效率。
内容的提问来源于stack exchange,提问作者User9211
相关产品推荐
相关产品推荐

