メモリ確保可能量の違い

[戻る]
ジロー 2006/03/25(土) 05:26:09
こんにちは、質問させてください。

画像を面でメモリに確保し、処理するプログラムを作成したのですが、
Win2000で上限としていた最大サイズに比べて、
WinXPで限界となる最大サイズがかなり少なくなってしまった為困っています
なぜこのようになってしまうか、
何か情報をお持ちの方いらっしゃらないでしょうか。

GlobalAllocPtrで指定サイズ分メモリを確保するプログラムを
VC++ 6.0で作成したのですが、私がテストしたパソコンでは
プログラムを実行したOS別に確保できた最大バイト数が違ってしまいました。

WinXP SP2 日本語版 約900MBが最大
WinXP SP2 英語版 約1.4GBが最大
Win200 SP4 日本語版 約1.8GBが最大
(全部Professionalです)

OSは、OS毎にHDDを用意して(計3個)別々にインストールし、
同じパソコンで接続するHDDを切り替えながらテストしました。

パソコンには、メモリを1GB搭載していて、
OSの仮想メモリのサイズは最小・最大とも4095MBに揃えました。

そもそも面で確保・処理するからこんなことになるのですが、
どなたか情報をお持ちの方、教えてください。
よろしくお願いします。

isshi 2006/03/25(土) 16:54:14
>WinXPで限界となる最大サイズがかなり少なくなってしまった為困っています
>なぜこのようになってしまうか、
>何か情報をお持ちの方いらっしゃらないでしょうか。

OSによって、ロードされるDLLが違うとか。

プロセスごとに2GBの仮想アドレス空間が使用できますが、
たとえばその中間にDLLがロードされれば、連続で取得できるメモリは
1GB未満となります。

Dependency Walker でどのDLLがどこにロードされたか調べることができます。
http://www.dependencywalker.com/

ジロー 2006/03/25(土) 18:19:28
isshi さん、どうもありがとうございます。
月曜日、会社にいって比較してみます。
いままで、あまり使ったことがなかったので、
使い方を勉強しないと・・・。
とにかくありがとうございました。

kure 2006/03/26(日) 00:35:37
DependencyWalker

kure 2006/03/26(日) 00:36:52
ぁぅ
すいません。途中でsubmitしちゃいました;

えと、DependencyWalker使わなくてもVisualStudioの
デバッグ機能で、どのモジュールがどのアドレスに
ロードされてるか見ることが出来ます。

適当なところでブレークして
モジュール一覧を表示させてみてください。

ITO 2006/03/26(日) 11:42:48
逆に質問のようになってしまいますが、
VisualC Ver 6.0 だとサービスパックによってWindowXPの対応が
変わってきませんでしょうか。

通常はSP3以上(出来れば多分SP5)ならOKだと思いますが、今回のジローさんの
質問のように微妙な違いだとありそうな感じがするのですが。

え〜いち 2006/03/27(月) 10:40:50
質問へ回答ではないのですが・・・
私も大きな画像を扱っての色変換等を行っています
この場合、ライン単位、ストリップ単位で処理しています
アプリケーションには処理速度が求められています
画像を全部読み込んで処理した方が早いように思うかもしれませんが、実際にはこれだと
スワップしてしまうので、処理速度が大幅にダウンしてしまうからです
まったく回答になっていませんね
あくまでも参考までに

ジロー 2006/03/27(月) 11:50:37
[[解決]]
こんにちは、
情報をくさだった方々、どうもありがとうございました。

ITOさん、VC++6 SP6です。
え〜いちさん、おっしゃるとおりですね。(苦)

Dependency workerで調べたら、やはり、DLLなどが挟まってました。
こんな感じです。(抜き出し方が悪いかもしれないですが。)

LoadLibraryA("C:\WINDOWS\IME\IMJP8_1\Dicts\IMJPCD.DIC") returned 0x3B100000.
Loaded "IMJP81.IME" at address 0x4EDC0000.  Successfully hooked module.
Loaded "UXTHEME.DLL" at address 0x58730000.  Successfully hooked module.
Loaded "COMCTL32.DLL" at address 0x5AB60000.  Successfully hooked module.
Loaded "LPK.DLL" at address 0x60740000.  Successfully hooked module.
Loaded "IMJP81K.DLL" at address 0x648F0000.  Successfully hooked module.

10MBずつ可能な限りメモリを確保して行くプログラムを作り、
確保できたところをマップしていくと、一致します。

0x038B0000 - 0x3A8AFFFF (0x37000000)
==> IMJPCD.DIC at 0x3B100000
0x3B120000 - 0x4E71FFFF (0x13600000)
==> IMJP81.IME at 0x4EDC0000
0x4EE20000 - 0x5841FFFF (0x09600000)
==> UXTHEME.DLL at 0x58730000
0x58770000 - 0x5A56FFFF (0x01E00000)
==> COMCTL32.DLL at 0x5AB60000 
0x5AC00000 - 0x605FFFFF (0x05A00000)
==> LPK.DLL at 0x60740000
0x60750000 - 0x6434FFFF (0x03C00000)
==> IMJP81K.DLL at 0x648F0000 
0x649C0000 - 0x72FBFFFF (0x0E600000)
(以下、略)

日本語版XPだと、IMJPCD.DICで引っかかります。約900Mバイトです。

IMJPCD.DICと、IMJP81.IMEは英語版なら関係ないので、
UXTHEME.DLLで引っかかる筈。約1.4Gバイト。
(すみません、検証はしてないです)

Win2000だと、こういったモジュールは、
0x6C7XXXXX以降の後ろの方にロードされてました。
なので、約1.8Gバイトの連続空間があいてます。

ざっと検索して見たんですが、
LPK.DLLでWin2003srvの話がレポートされていました。
http://support.microsoft.com/?scid=kb;ja;908132&spid=3198&sid=346

モジュールのいくつかは、
XPのいらないファイルだとされてて、削除する人もいるみたいです。
でも、普通の人には、ちょっとレベル高いですね。
お客さんには、理由を説明して諦めてもらおうかなと思います。

あと、蛇足が2点。

詳しく、調べてないですが、
コンソールアプリだと、日本語XPでも1.8GBぐらい取れたりします。もー。

マップは、GlobalAllocPtrだと、隙間があいてしまうので、
VirtualAllocで作成しました。
一応これも、VirtualAllocが進められる理由でしょうか。。。

どうもありがとうございました。

kure 2006/03/27(月) 14:02:13
もう見てないかもしれないですが。。。

UI表示前にメモリ確保すればIME関連のDLLとか
に邪魔されずに済むと思います。
遅延ロードを有効にすると更に事前ロードされるDLLが減らせるかもしれないですね。

自作DLLであればrebase.exeを使えば
デフォルトのロード先のアドレスを変更できるので
ある程度まとまった領域に配置されるようにすることはできます。
(アドレスが使われているとあいてる場所にマップされちゃいますが^^;)

今回の話はIMEに限らずExplorerの拡張とかをやってても発生する
可能性があるので単純にあきらめるというよりは
「連続した広大なメモリを確保しなければならない」っていう
仕様を直した方が良さそうですね。

ジロー 2006/03/27(月) 19:31:36
Kureさんどうもありがとうございます。

> もう見てないかもしれないですが。。。

もしかしたら、
マップされる場所を指定する方法を教えてくれる人がいるかもと思いまして。。。

> UI表示前にメモリ確保すればIME関連のDLLとか
> に邪魔されずに済むと思います。

IME関連のモジュールは後ろに追いやることができました。
1.4GBまで確保できました。

> 遅延ロードを有効にすると更に事前ロードされるDLLが減らせるかもしれないですね。

UXTHEME.DLLとCOMCTL32.DLLを遅延ロードでやってみたんですが、
今回、はじめてなもので、効果が良くわからなかったです。(残念)
VisualStadioからデバッグで実行するとそもそも遅延ロードのようになるのか、
そももそ早い段階でDLLが使われてしまうのか、今ひとつ把握できてません。
これは、もう少し経験値を上げないと理解できなさそうな雰囲気です。

> 自作DLLであればrebase.exeを使えば
> デフォルトのロード先のアドレスを変更できるので
> ある程度まとまった領域に配置されるようにすることはできます。
> (アドレスが使われているとあいてる場所にマップされちゃいますが^^;)

画像処理ボードからDMAした利するときdriverとDLLが絡むんですが役立ちそうです。
まだ、困ったことは無いですが、
最近は512MBバイトを超えるものを複数チャンネル転送するとかいうのがあるので、
デマンドDMAなんかすることになると、必要かもしれません。

> 今回の話はIMEに限らずExplorerの拡張とかをやってても発生する
> 可能性があるので単純にあきらめるというよりは
> 「連続した広大なメモリを確保しなければならない」っていう
> 仕様を直した方が良さそうですね。

おっしゃる通りですね、週末はそればかり考えてました。
画像処理プログラムはライン単位のバッファでも、手間はかわらないので
これから作るプログラムは方針変更ですね。

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