2

次のコードでは、セグメンテーション違反が発生します。

bool primeNums[100000000]; // index corresponds to number, t = prime, f = not prime

for (int i = 0; i < 100000000; ++i)
{
    primeNums[i] = false;
}

ただし、配列宣言を動的に変更すると、次のようになります。

bool *primeNums = new bool[100000000];

私はセグフォルトを取得しません。これがなぜなのかについての一般的な考えがあります。最初の例では、メモリがスタックに置かれていますが、動的なケースではヒープに置かれています。

これについて詳しく説明していただけますか?

4

4 に答える 4

6
bool primeNums[100000000];

stackしたがって、巨大なサイズの静的配列を割り当てるのに十分なスタック領域がないため、セグメンテーション違反が発生します。

に動的配列が割り当てられているheapため、セグメンテーション違反が発生するのはそれほど簡単ではありません。動的配列はnewC++ を使用して作成され、メモリを割り当てるために呼び出しoperator new、次にコンストラクタを呼び出して割り当てられたメモリを初期化します。

どのように機能するかについての詳細operator newは、以下の標準から引用されています [new.delete.single]:

必要な動作:

適切にアラインされたストレージ (3.7.3) への非 null ポインターを返すか、bad_alloc 例外をスローします。この要件は、この機能の代替バージョンを拘束します。

デフォルトの動作:

— ループの実行: ループ内で、関数は最初に要求されたストレージの割り当てを試みます。この試みが標準 C ライブラリ関数 malloc の呼び出しを伴うかどうかは未規定です。

— 試行が成功した場合、割り当てられたストレージへのポインタを返します。それ以外の場合、set_new_handler() への最後の引数がヌル ポインターであった場合は、bad_alloc をスローします。

— それ以外の場合、関数は現在の new_handler (18.4.2.2) を呼び出します。呼び出された関数が戻ると、ループが繰り返されます。

— 要求されたストレージの割り当てが成功した場合、または呼び出された new_handler 関数が返されなかった場合、ループは終了します。

したがって、動的配列をnewで使用すると、十分なスペースがないbad_alloc場合、デフォルトでスローされます。この場合、セグメンテーション違反ではなく例外が表示されます。配列サイズが巨大な場合は、動的配列または標準コンテナーを使用することをお勧めします。ベクターなど。

于 2013-04-29T01:12:49.233 に答える
0

一部のコンパイラまたはオペレーティング システムでは、スタックのサイズが制限されています。Windows では、デフォルトは 1 MB ですが、変更できます。

于 2013-04-29T01:14:08.507 に答える
0

最初のケースでは、スタックにメモリを割り当てます:

bool primeNums[100000000]; // put 100000000 bools on stack

for (int i = 0; i < 100000000; ++i)
{
    primeNums[i] = false;
}

ただし、これはヒープへの割り当てです。

bool *primeNums = new bool[100000000]; // put 100000000 bools in the heap

スタックは(非常に)制限されているため、これがセグメンテーション違反の理由です

于 2013-04-29T01:18:39.077 に答える