私のPCには2GBのRAMメモリがあります。C# 2008 Express Edition で 70.000 項目の配列を持つ 3D メッシュ オブジェクトを形成すると、「スタック オーバーフローの例外が処理されました...」というエラー メッセージが表示されます。RAM メモリを 2 GB から 4 GB にアップグレードすると、このエラー メッセージを解決できますか?
7 に答える
ほぼ間違いなく。(メモリ不足ではなく)スタックオーバーフローは、割り当てられたスタックスペースを消費したことを意味しますが、スタックは(比較的)小さいです。ヒープはそれがすべて起こっているところです...
オプション:
- 無限再帰のバグを修正してください...
- データを配列/リスト/ヒープベースのストアに移動します(現時点ではどこにありますか?)
- 深い再帰を避ける
- 特大の構造体は避けてください...本当にクラスであるはずの大きな太った構造体はありますか?(構造体は、まばたきするほど自分自身をコピーします)
- 転倒するだけで、大きなリファクタリングの価値がないと確信している場合は、スタックスペースを増やします(この回答は嫌いです)。これを行うには、より大きなスタックで独自のスレッドを生成する必要があります。
いいえ。RAMを増やしてもスタックサイズは増えません。
スタックオーバーフロー(おそらく再帰が原因)を引き起こしているコードを書いているので、それを修正する必要があります。
物理メモリは、マシンで実行されているプログラムのパフォーマンスにのみ影響を与えますが、プログラムのメモリ関連の問題とは何の関係もありません (標準のオペレーティング システムでは、埋め込みシステムは異なる規則に従います)。
まず、この間違いを何度も見たことがあるので、オペレーティング システムのメモリ モデルについて話しましょう。
ほぼすべてのユーザー オペレーティング システム (ここでは Linux、Windows、BSD などについて考えています) は、仮想メモリ モデルを使用しています。仮想メモリ モデルとは、各プログラムにプライベート仮想メモリへのフル アクセスが与えられることを意味します。つまり、対応する物理メモリを持たなくてもよいメモリ ストレージの表現です。
この仮想メモリのサイズは、1 つのマシン レジスタでアドレス指定できる範囲と同じです。32 ビット オペレーティング システムでは、約 4GB を意味します。これで、システムの実際のメモリ量に関係なく、プログラムは常に 4GB だと認識します。
実際、これらの 4 GB は、プログラムと、オペレーティング システムがカーネル モードでデータを処理し、プログラムに必要な構造を維持するために予約するスペースとの間で共有されます。実際には、構成 (OS 構成) に応じて、約 2 GB または 3 GB と数えることができます。これはすべて、使用している物理メモリの量とは関係ありません。256 MB の RAM を使用できますが、プログラムは 2GB を自由に使用できると認識します。
メモリを割り当てるとき、システムは通常、要求した正確な量のメモリを提供しません。代わりに、プロセスに割り当てられた予約済みメモリ (たとえば 4KB) のブロックであるページを使用します。これを行うと、OS はその「ページ」を割り当て済みとして登録しますが、これはまだ仮想メモリ内にあります。内部的に、OS は、これらのページのどれが物理メモリに保持され、どのページが (HDD に) スワップされているかを管理します。これが、RAM を増やすとパフォーマンスが向上する理由です (同時にメイン メモリに格納できるページが増え、HDD から読み取る必要のあるページが少なくなります) が、スタック オーバーフロー (または道)。
そのため、RAM を増やしても効果がありません。
最後に、スタック オーバーフローの例外については、実際のコードを見ないとわかりませんが、いくつかの適切な回答が既に与えられています。
ほとんどのスタック オーバーフローは、直接的または間接的 (A-->B-->C-->A) の無限再帰から発生しますが、具体的なケースでは、スタック内の多くのデータに割り当てているだけだと思います。
サイズが 70000 の配列があります。配列はスタックに割り当てられている値の型でいっぱいであると推測しています.正しく思い出すと(これを事実と見なさないでください).NETでは1MBであり、これが原因である可能性がありますあなたのスタックオーバーフロー。
おそらくそうではありません。スタックサイズを増やす必要があります。これがエラーメッセージの内容です。
編集:または、コードに含まれる可能性のある無限再帰を修正します。
スタック オーバーフローは、無限再帰または非常に深くネストされた再帰を意味する場合があります。
ちなみに、末尾再帰メソッドがある場合、x64 JITter はそれらを最適化し、スタック オーバーフローにまったく遭遇しません (そして、無限再帰は...無限になります)。
そのため、64 ビット OS にアップグレードするか、コードを修正して、この問題が発生しないようにすることができます (再帰が深すぎるというよりも、バグである可能性が高いです...)。
実は違う。しかし、別の理由があります。boot.ini で特定の起動オプションを指定しない限り、Windows XP は最大 2 GB しか処理できません。(/3gb パラメータ。) せいぜい、Windows XP と Vista は 3 GB の RAM まで使用できますが、これは基本的に Windows の制限です。これらの制限の詳細については、このリンクを参照してください。
RAM を増やし、アプリケーションを修正して 2 GB の制限を超えるようにすると、スタックのサイズが増加する可能性があるため、スタック オーバーフローが修正される可能性があります。また、提案されているように、コードが無限の再帰ループにあり、リソースがなくなるまで実行し続けるため、このスタック オーバーフローの瞬間を遅らせるだけかもしれません。
再帰を使用する場合は、次の点に注意してください。再帰を使用して行うことは、再帰を使用しなくても書き直すことができます。コードが読みにくくなりますが、この規則に例外はありません。
I dont know for C#, but in java, stackoverflow error means that you are creating instance of an class in the class that have been already instanced in the class you are trying to instance