new以外でCMemoryException発生しますか?

[戻る]
ちゃっぴ 2008/04/25(金) 09:36:40
VC7.1で作成しているアプリで、あまりに大きなファイルを入力すると、
CMemoryExceptionで落ちる現象が発生しています。

その時点のページファイルが2Gを超え、
Win32アプリが使えるMAXのメモリサイズを超えようとしたことが
原因ととりあえず予想しているのですが・・・

しかし、newする箇所ではCMemoryExceptionをキャッチできません。

本当にメモリ不足なのか・・実はメモリ破壊等のバグではないか
心配になり、質問させて頂きました。

意図的にメモリを確保しない、変数への代入等でもメモリ不足になれば
CMemoryExceptionは発生するのでしょうか?

ちなみに、現象が発生する入力ファイルのサイズは、動作保証外なので、
理由がメモリ不足ならば、エラーで落ちることはかまわないと考えています。

シャノン 2008/04/25(金) 09:49:25
スタックトレースして、MFC のソースコード等見ても、どこでも new していないことは
確認済みですか?

> 意図的にメモリを確保しない、変数への代入等でもメモリ不足になれば
> CMemoryExceptionは発生するのでしょうか?

プリミティブ型では発生しないでしょうが、コピーコンストラクタの実装次第では発生し
うるでしょうね。

ちゃっぴ 2008/04/25(金) 10:36:05
シャノンさん、ご回答ありがとうございます。

CMemoryExceptionが発生している辺りでは、CMapのSetAtを使っているのですが、
そのMFCソースをみると、どうもnewしているような・・・

pragma push_macroがいまいち理解できないのですが、
これって結果的にnewしているのでしょうか。

CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>::NewAssoc(ARG_KEY key)
{
 省略
#pragma push_macro("new")
#undef new
    ::new(pAssoc) CMap::CAssoc(key);
#pragma pop_macro("new")
 return pAssoc;
}

PATIO 2008/04/25(金) 11:04:46
newがdefineされていた時の対策にいったん退避して
newをundefしてグローバルのnewを呼んでいると思います。
で、退避した定義を元に戻していると。

ちゃっぴ 2008/04/25(金) 11:16:07
PATIOさんご回答ありがとうございます。

なるほど、「#pragma push_macro」「#pragma pop_macro("new")」の意味が
分かりました。

CMapのSetAtの中で「new」があるためCMemoryExceptionが発生する場合が
あるのですね。

ということは、今回のエラーは、メモリ不足と理解して問題ないような・・・

みなさん、ありがとうございました。

PATIO 2008/04/25(金) 13:11:34
ちなみにですが、
「#pragma push_macro」「#pragma pop_macro」はネットで検索すれば一発で出てきますよ。
分からないときは一つ一つ調べてみる事をお勧めします。

http://blogs.wankuma.com/melt/archive/2007/09/07/94656.aspx

ITO 2008/04/25(金) 15:47:34
> CMemoryExceptionが発生している辺りでは、CMapのSetAtを使っているのですが、
> そのMFCソースをみると、どうもnewしているような・・・
サポート技術情報で問題視されてなければ大丈夫だと思います。

CMapはあまり使ってないんでわからないのですが、
InitHashTableで初期化・サイズ指定をしないといけないんじゃないでしょうか?

> その時点のページファイルが2Gを超え、
本来どのぐらい必要なんですか?
多すぎるとWindows環境によって動かない場合があります。

ちゃっぴ 2008/04/30(水) 10:14:48
PATIOさん、ITOさんご回答ありがとうございました。
また、返答が遅くなってしまい、すみません。

PATIOさん
載せていただいたサイト、質問する前に読んでいたのですが、
私にはよく理解できず・・・
PATIOさん「退避」という言葉を読んで、やっと理解できました。
ありがとうございます。

ITOさん
>サポート技術情報で問題視されてなければ大丈夫だと思います。
ヘルプやその他も調べてみたのですが、CMap::SetAtでメモリが確保できなかった場合
についての記載はありませんでした。

>CMapはあまり使ってないんでわからないのですが、
>InitHashTableで初期化・サイズ指定をしないといけないんじゃないでしょうか?
確認してみましたが、CArrayのように、最初に要素数(エントリ数)を指定したほうが、
パフォーマンスが良い、と理解しました。
今回のケースでは、実際のエントリ数と最大のエントリ数に大きな差がある場合が
多いので、あらかじめエントリ数を指定するということは考えていませんでした。
CMap::SetAtのヘルプに書かれている使用例をみると、InitHashTableをせずSetAtして
いるので、そのようなやり方でも問題はないのかと思っています。

>本来どのぐらい必要なんですか?
必要メモリサイズは、入力ファイルサイズにほぼ比例して増えていく作りです。

>多すぎるとWindows環境によって動かない場合があります。
これは、もちろん理解しています。
動作保証サイズの入力ファイルにて、推奨スペック以上のPCで処理が実行できることは
確認済みです。
その上で上記に当てはまらない場合の動作はユーザー責任というスタンスです。

ちゃっぴ 2008/04/30(水) 10:19:07
[[解決]]
解決にチェック忘れました。

古いスレッドには追加発言できません。