You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现埃氏筛法时大数组引发段错误的解决方法

解决C语言埃氏筛法中数组过大导致的段错误问题

你遇到的Segment fault本质是栈空间不足:代码里用了变长数组bool pPrimes[n],这种数组会被分配在程序的栈(stack)上,而栈的默认大小通常只有几MB(比如Linux下一般是8MB左右)。当n达到千万级甚至更大时,数组所需内存会直接超过栈的上限,触发段错误。

解决办法

1. 使用堆内存分配(最推荐)

把栈上的数组改成用malloc分配堆内存,堆的可用空间远大于栈,能轻松支持超大n的需求,记得用完后用free释放内存避免泄漏:

#include <stdio.h>
#include <stdbool.h> 
#include <math.h>
#include <time.h>  
#include <limits.h>
#include <stdlib.h>  // 引入malloc/free所需头文件
     
int main(){
    clock_t t;
    t = clock();

    int n = 1299710;
    
    // 分配堆内存,必须检查是否分配成功
    bool *pPrimes = malloc(n * sizeof(bool));
    if (pPrimes == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    
    for(int i = 0; i<n; i++){
        pPrimes[i] = true;
    }
    
    pPrimes[0] = false;
    pPrimes[1] = false;

    for(int i = 2; i<sqrt(n); i++){
        if(pPrimes[i]){
            for(int x = i*i; x<n; x+=i){
                pPrimes[x] = false;
            }
        }
    }

    for(int i = 2; i<n; i++){
        if (pPrimes[i]){
            printf("%d\n", i);
        }
    }
    t = clock() - t;
    double time_taken = ((double)t)/CLOCKS_PER_SEC; 
 
    printf("%f", time_taken);

    free(pPrimes);  // 释放堆内存
    return 0;
}

2. 内存压缩优化(支持更大n)

埃氏筛法中每个元素只需要存布尔状态,可以用位运算压缩内存,比如用unsigned char存储8个状态,把内存占用降到原来的1/8,能支持数倍于原大小的n:

#include <stdio.h>
#include <math.h>
#include <time.h>  
#include <limits.h>
#include <stdlib.h>

// 位操作宏定义
#define SET_BIT(arr, idx)    (arr[idx/8] |= (1 << (idx%8)))
#define CHECK_BIT(arr, idx)  (arr[idx/8] & (1 << (idx%8)))
#define CLEAR_BIT(arr, idx)  (arr[idx/8] &= ~(1 << (idx%8)))

int main(){
    clock_t t = clock();
    int n = 1299710;
    
    // 计算所需字节数(向上取整n/8)
    size_t byte_size = (n + 7) / 8;
    unsigned char *pPrimes = malloc(byte_size);
    if (pPrimes == NULL) {
        printf("内存分配失败\n");
        return 1;
    }
    
    // 初始化所有位为1(默认标记为质数)
    for(size_t i = 0; i < byte_size; i++){
        pPrimes[i] = 0xFF;
    }
    // 0和1不是质数
    CLEAR_BIT(pPrimes, 0);
    CLEAR_BIT(pPrimes, 1);

    for(int i = 2; i < sqrt(n); i++){
        if(CHECK_BIT(pPrimes, i)){
            for(int x = i*i; x < n; x += i){
                CLEAR_BIT(pPrimes, x);
            }
        }
    }

    for(int i = 2; i < n; i++){
        if(CHECK_BIT(pPrimes, i)){
            printf("%d\n", i);
        }
    }

    double time_taken = ((double)(clock() - t))/CLOCKS_PER_SEC; 
    printf("%f", time_taken);

    free(pPrimes);
    return 0;
}

3. 全局数组替代(不推荐超大n)

如果把数组声明为全局变量,它会被分配在静态存储区(而非栈),静态区空间比栈大,但全局变量会一直占用内存直到程序结束,灵活性不如堆分配,仅适合中等规模的n:

#include <stdio.h>
#include <stdbool.h> 
#include <math.h>
#include <time.h>  
#include <limits.h>   

#define MAX_N 1299710
bool pPrimes[MAX_N];  // 全局数组

int main(){
    clock_t t;
    t = clock();

    int n = MAX_N;
    
    for(int i = 0; i<n; i++){
        pPrimes[i] = true;
    }
    
    pPrimes[0] = false;
    pPrimes[1] = false;

    for(int i = 2; i<sqrt(n); i++){
        if(pPrimes[i]){
            for(int x = i*i; x<n; x+=i){
                pPrimes[x] = false;
            }
        }
    }

    for(int i = 2; i<n; i++){
        if (pPrimes[i]){
            printf("%d\n", i);
        }
    }
    t = clock() - t;
    double time_taken = ((double)t)/CLOCKS_PER_SEC; 
 
    printf("%f", time_taken);

    return 0;
}

内容的提问来源于stack exchange,提问作者Simon Klyvare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:35:23