web-dev-qa-db-ja.com

大きな配列を宣言するときにスタックオーバーフロー例外を取得する

次のコードは私のためにスタックオーバーフローエラーを生成しています

int main(int argc, char* argv[])
{
    int sieve[2000000];
    return 0;
}

どうすればこれを回避できますか? Turbo C++を使用していますが、コードをCのままにしておきたい

編集:

アドバイスをありがとう。上記のコードはほんの一例です。実際には、サブメインではなく関数で配列を宣言しています。また、配列をゼロに初期化する必要があったため、mallocをグーグルで検索したところ、callocが自分の目的に最適であることがわかりました。

Malloc/callocには、変数を使用してサイズを宣言できるという利点があります。

41

配列が大きすぎてスタックに収まらない場合は、ヒープの使用を検討してください。

int *sieve = malloc(2000000 * sizeof(*sieve));

本当にスタックサイズを変更したい場合は、 このドキュメントをご覧ください。

ヒント:-動的に割り当てられたメモリが不要になったときに、それを解放することを忘れないでください。

57
arul

3つの方法があります:

  1. ヒープに配列を割り当てます-他のポスターが示唆しているように、malloc()を使用します。 free()することを忘れないでください(ただし、main()の場合、それほど重要ではありません。OSはプログラムの終了時にメモリをクリーンアップします)。
  2. ユニットレベルで配列を宣言します-配列はデータセグメントに割り当てられ、すべての人に表示されます(宣言にstaticを追加すると、ユニットへの表示が制限されます)。
  3. 配列をstaticとして宣言します。この場合、配列はデータセグメントに割り当てられますが、main()でのみ表示されます。
12
qrdl

スタックではなく、ヒープに割り当てる方がよいでしょう。何かのようなもの

int main(int argc, char* argv[])
{
    int * sieve;
    sieve = malloc(20000);
    return 0;
}
2
Cogsy

Mallocを使用します。戻り値の型がnullでないことをすべて確認します。nullの場合、システムにはその数の値を収めるのに十分なメモリがありません。

1
asdf

これは約7MBのスタックスペースです。 Visual Studioでは、/ STACK:###、###を使用して必要なサイズを反映します。本当に巨大なスタックが必要な場合(LISPなどを使用するのが妥当な理由かもしれません:)、ヒープがVirtualAllocの使用を強制する前に小さなsh割り当てに制限されている場合でも、PEを設定してビルドすることもできます/ LARGEADDRESSAAWARE(Visual Studioのリンカ)。ただし、これはPEヘッダーを構成して、コンパイルされたバイナリが4GBの32ビットアドレス空間全体をアドレス指定できるようにします(WOW64で実行されている場合)。真に大規模なバイナリを構築する場合は、通常、/ bigobjを追加のリンカーパラメータとして構成する必要があります。

さらに多くのスペースが必要な場合は、(MSVCのリンク)/ merge:に似たものを使用することで、規則に根本的に違反する可能性があります。これにより、あるセクションを別のセクションにパックできるため、単一の共有コードにすべてのバイトを使用できます。/dataセクション。当然、defファイルまたは#pgramaでSECTIONS権限を構成する必要もあります。

1

あなたの配列は巨大です。

お使いのマシンまたはOSにそれほど多くのメモリがないか、割り当てたくない可能性があります。


どうしても巨大な配列が必要な場合は、動的に(malloc(...)を使用して)割り当てることができますが、メモリリークが発生するリスクがあります。メモリを解放することを忘れないでください。

Mallocの利点は、スタックではなくヒープにメモリを割り当てようとすることです(したがって、スタックオーバーフローが発生しません)。

Mallocが返す値をチェックして、割り当てが成功したか失敗したかを確認できます。失敗した場合は、小さい配列をmallocしてみてください。


別のオプションは、その場でサイズ変更できる別のデータ構造を使用することです(リンクリストなど)。このオプションが適切かどうかは、データをどのように処理するかによって異なります。

さらに別のオプションは、ファイルにデータを保存し、その場でデータをストリーミングすることです。このアプローチは最も遅いです。

ハードドライブにストレージを使用する場合は、既存のライブラリ(データベース用)を使用することもできます。

0
Ivan Rubinson

Turbo C/C++は16ビットコンパイラであるため、intデータ型は約2バイトを消費します。 2バイト* 2000000 = 40,00,000バイト= 3.8147MBのスペース。

関数の自動変数はスタックに格納され、スタックメモリのオーバーフローを引き起こしました。代わりに、データメモリ[静的またはグローバル変数を使用]または動的ヒープメモリ[malloc/callocを使用]を使用して、プロセッサメモリマッピングの可用性に応じて必要なメモリを作成します。

0
Arun Chettoor

オブジェクトが実際に必要な大きさに基づいて、alloca()を使用してスタックフレームに必要なスペースを割り当てることができない理由はありますか?

それを実行してもスタックを破壊する場合は、割り当てられたヒープに配置します。 main()で静的として宣言せず、データセグメントに配置することを強くお勧めします。

それが本当に大きくなければならず、プログラムがそれをヒープに割り当てることができない場合、プログラムはそもそもそのタイプのマシンで実行されているビジネスを実際には持っていません。

あなたは(正確に)何を達成しようとしていますか?

0
Tim Post