プログラムが多数のメモリ割り当て例外をスローするという問題があり、問題を診断するのに非常に苦労しています...コードを投稿しますが、プログラムが非常に大きく、独自の情報に関する懸念があるため、コードを投稿せずに助けを得たいと思っています。なんらかの形式の SSCCE コメントで返信する予定がある場合は、今すぐ読むのをやめて、私たち二人の時間を節約してください。これは、簡潔なコードを投稿できない場合です。問題の説明といくつかの特定の質問について、できるだけ明確かつ簡潔にしようとします。
プログラムの背景- 私のプログラムは基本的にデータ処理ツールです。一連のデータ テーブルを入力として受け取り、それらに対して計算を実行し、計算結果に基づいて新しいデータ テーブルを吐き出します。私のデータ構造はすべてユーザー定義のクラスです (配列のベクトル コンテナーを持つ int、double、および string 型で構成されています)。いずれの場合も、new と delete を使用せずにクラス変数のインスタンスを開始します。
問題の説明- 私のプログラムは警告なしでコンパイルされ、小さなデータセットで問題なく動作します。ただし、データセットを増やすと (20x80 配列から 400x80 に)、bad_alloc 例外をスローし始めます (最初の 35 エントリ程度を処理すると)。大規模なデータセットは、18 個のモジュールのうち 17 個で正常に実行されます。エラーが発生している 1 つの関数を分離しました。この関数に必要な計算では、約 30,000 行のデータが作成されますが、コード内の他の関数では 800,000 行以上が問題なく生成されます。
このモジュールの唯一の固有の属性は、サイズ変更を頻繁に使用していること (関数呼び出しごとに約 100 回) と、関数がサイズ変更操作中に再帰ループを使用していることです (関数は、建物の 1 つのテナントから平方フィートを割り当てています)。すべての平方フィートが割り当てられるまで、各テナント リースのサイズと期間がシミュレートされた後、割り当てられる残りのフィートを更新します)。また、エラーは毎回ほぼ同じ場所で発生しています (ただし、結果に何らかの変動をもたらす乱数ジェネレーターがあるため、まったく同じ場所ではありません)。私を本当に困惑させているのは、この関数への最初の ~34 回の呼び出しが正常に機能し、~35 回の呼び出しでは前の 34 回よりも多くのメモリを必要としないにもかかわらず、35 回目の呼び出しでこれらの bad_alloc 例外が発生しているということです...
コードなしで支援するのは難しいことを私は知っています。私に何か方向性を教えてください。私の具体的な質問は次のとおりです。
「new」と「delete」を使用しておらず、すべての変数がローカル関数の内部で初期化されている場合、関数呼び出しを繰り返すことでメモリ リークや割り当ての問題が発生する可能性はありますか? 「ベクターインスタンス」を使用してローカル関数の変数インクルードを初期化するときに、メモリを管理するためにできること、またはすべきことはありますか? 私の変数を宣言するには?
スタックを介してプログラム全体を実行している場合、スタックメモリが不足している可能性はありますか? 大きなルックアップ テーブル (マップなど) の一部をヒープにロードし、速度が重要な反復にスタックを使用する必要がある可能性はありますか?
サイズ変更を頻繁に使用すると、メモリに関連する問題はありますか? これは、"new" と "delete" を使用する必要がある場合でしょうか (多くの場合、非常に強い特定の理由がない限り、これらを使用しないように警告されています)。
[関連 3] 問題関数内で、クラス変数を作成し、その変数を約 20 回 (モデルの「反復」ごとに 1 回) 上書きしています。これを行うとき、前の反復からのデータは必要ありません...したがって、表向きは反復ごとに変数の新しいインスタンスを作成できますが、これがどのように役立つかはわかりません(明らかに私ができるので最初の ~34 個のデータ スライスの 1 つのインスタンスで 20 回の反復すべてを実行するため)
任意の考えをいただければ幸いです。いくつかのコードを投稿しようとすることはできますが、私はすでに一度それを試しましたが、コンパイルできないという事実に誰もが気を取られているようでした. 問題の関数を投稿できますが、それ自体はコンパイルされません。
問題を引き起こしているクラスは次のとおりです。
// Class definition
class SpaceBlockRentRoll
{
public:
double RBA;
string Tenant;
int TenantNumber;
double DefaultTenantPD;
int StartMonth;
int EndMonth;
int RentPSF;
vector<double> OccupancyVector;
vector<double> RentVector;
};
// Class variable declaration (occuring inside function)
vector<SpaceBlockRentRoll> RentRoll;
また、ここに再帰が発生する関数のスニペットがあります
for (int s=1; s<=NumofPaths; ++s) {
TenantCounter = 0;
RemainingTenantSF = t1SF;
if (RemainingTenantSF > 0) {
while (RemainingTenantSF > 0) {
TenantCounter = TenantCounter + 1;
// Resize relevant RentRoll vectors
ResizeRentRoll(TenantCounter, NumofPaths, NumofPeriods, RentRoll);
// Assign values for current tenant
RentRoll[TenantCounter] = AssignRentRollValues(MP, RR)
// Update the square feet yet to be allocated
RemainingTenantSF = RemainingTenantSF - RentRoll[TenantCounter].RBA;
}
}
}