2

Cでプログラムに取り組んでいます。長さが1,000,000の配列を初期化したい
エラーや警告なしでコンパイルされますが、実行時にWindowsがプロセスの終了を送信します。
コードを変更して、それぞれが500,000個の整数を持つ4つの配列になるようにしました。エラーや警告なしで再度コンパイルされますが、問題は依然として存在します。

私はCodeBloxを使用しています(GCCコンパイラだと思います)

これが私のコードです:

#include <stdio.h>
#include <math.h>
// Prototypes:
int checkprime(int n);

int main(){
int m=0;

    int A[500001]={2,2,0};//from k=1 to 500000
    int B[500000]={0};//from k=500001 to 1000000
    int C[500000]={0};//from k=1000001 to 1500000
    int D[500000]={0};//from k=1500001 to 2000000
    int n=3;
    int k=2;
        for(n=3;n<2000001;n +=2){
            if(checkprime(n)){

                if (k<=500000)
                {A[k]=n;
                k +=1;}

                else if ((k>500000)&&(k<=1000000))
                {B[k-500001]=n;
                k +=1;}
                else if ((k>1000000)&&(k<=1500000)){
                C[k-1000001]=n;
                    k +=1;
                }
                else if(k>1500000){
                D[k-1500001]=n;
                k +=1;}
                }//end of if

            }//end for

    int i=0;
    for(i=1;i<500001;i++)
    {
        m=m+A[i];
    }
    for(i=0;i<5000001;i++)
    {
        m=m+B[i];
    }
    for(i=0;i<5000001;i++)
    {
        m=m+C[i];
    }
    for(i=0;i<5000001;i++)
    {
        m=m+D[i];
    }
    printf("answer is %d",m);
return 0;//Successful end indicator
}//end of main

int checkprime(int n){
int m=sqrt(n);
if (!(m%2))
{
    m=m+1;
}
int stop=0;
int d=0;
int isprime=1;
while((m!=1)&&(stop==0)){
d=n%m;
if (d==0){
    stop=1;
    isprime=0;
    }
m -=2;

}//end of while
return isprime;
}//end of checkprime
4

3 に答える 3

1

ulimit コマンドで制御される最大スタック サイズの制限。コンパイラは制限を小さく設定できます (または設定できません) が、それより大きくはできません。
現在の制限 (キロバイト単位) を確認するには:

ulimit -s

制限を解除するには:

ulimit -s unlimited
于 2012-07-28T08:48:58.630 に答える
1

初期化された巨大な配列が静的またはグローバルであることを願っています。ローカル変数の場合、実行時にスタックがオーバーフローします。

古いバージョンの GCC では、配列を初期化するときに、次善の動作 (おそらく 2 次時間) があったと思います。

また、 C標準では、準拠するすべてのコンパイラが受け入れる必要がある (小さい) 最小配列サイズを定義する可能性があると考えています (文字列サイズには下限があり、512 ほど小さい可能性があります)。

IIRC、最近のバージョンの GCC では、静的配列を初期化するときの動作が改善されました。GCC 4.7 で試す

私の Debian/Sid では、で始まるファイルgcc-4.7.1をコンパイルできます。biga.c

int big[] = {2 ,
 3 ,
 5 ,
 7 ,
 11 ,
 13 ,

で終わる

 399999937 ,
 399999947 ,
 399999949 ,
 399999959 ,
};

23105402 行を含む:

 % time gcc -c biga.c
 gcc -c biga.c  43.51s user 1.87s system 96% cpu 46.962 total

 % /usr/bin/time -v gcc -O2 -c biga.c
Command being timed: "gcc -O2 -c biga.c"
User time (seconds): 48.99
System time (seconds): 2.10
Percent of CPU this job got: 97%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:52.59
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 5157040
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 691666
Voluntary context switches: 25
Involuntary context switches: 5162
Swaps: 0
File system inputs: 32
File system outputs: 931512
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

これは、16Gb RAM を搭載した i7 3770K デスクトップ上にあります。

内部であっても、巨大な配列をローカルとして持つことmain 、常に悪い考えです。それらをヒープに割り当てるか (callocまたはまたは を使用して適切に) mallocfreeそれらをグローバルまたは静的にします。コール スタック上のローカル データ用のスペースは、常に恐ろしいリソースです。典型的な呼び出しフレーム (すべてのローカル変数の合計サイズ) は、1 キロバイト未満である必要があります。1 メガバイトを超える呼び出しフレームは、ほとんどの場合、質が悪く、専門的ではありません。

于 2012-07-28T06:24:11.770 に答える
0

はいあります。

ローカル配列はスタック上に作成され、配列が大きすぎると、スタックがメモリ内の何かと衝突し、プログラムがクラッシュします。

于 2012-07-28T06:23:49.200 に答える