固定メモリと移動可能メモリ – プログラミング – Home

固定メモリと移動可能メモリ
 
通知
すべてクリア

固定メモリと移動可能メモリ


エイリア
 エイリア
(@エイリア)
ゲスト
結合: 22年前
投稿: 1
Topic starter  

GlobalAlloc()関数のフラグに、GMEM_FIXEDと
GMEM_MOVEABLEがありました。これらは、
固定メモリと、移動可能メモリをそれぞれ確保すると
かいてありました。

固定メモリと、移動可能メモリは違うのでしょうか?
そして、それらの使い道を教えてください。
よろしくおねがいします


引用解決済
トピックタグ
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2659
 

名前のまんまなんですけれど、
固定メモリというのは、ユーザー側が開放しない限りアドレスが変更されないメモリブロック
を言います。この場合のアドレスは実際は物理的なメモリアドレスではなく仮想アドレスなん
ですが、この仮想アドレスと物理的なメモリアドレスの割付を固定してOS側で勝手に動かせな
いようにするのが目的です。
移動可能メモリは、通常は仮想アドレスとの割付が去れていないもので、この場合、仮想アドレ
スはフリーの状態なので急に大きな領域が必要になったときに仮想アドレスを大きく確保しやす

のでOSからみると移動可能メモリの方が運用しやすいということになります。
移動可能メモリはLockすることで仮想アドレスと結び付けられ、この状態では勝手にアドレス

変更されることはありません。
使用が終わったらUnlockして開放すれば、使用していた仮想アドレスも開放されてフリーの状
態に
なります。
移動可能メモリを使ってもLockしっぱなしでは、固定メモリと変わらないので移動可能メモリ

使うのでしたら、まめにLock/Unlockをしないと意味が無いです。


返信引用
島
 島
(@島)
ゲスト
結合: 22年前
投稿: 238
 

PATIOさんのご意見に対する補足としてお読みください

GMEM_MOVEABLE と GMEM_FIXED とは Win16 との互換性の為に残っているようなものだと
(勿論 C の runtime ライブラリーなんか使わないなどという場合は必要かもしれません)
わたしは考えています。
どうしても GlobalAlloc API が必要な場面はアプリケーションでは私には余り無く、
C++ の new か、C の malloc() かで済む場合がほとんどだったからです
クリップボードを扱う場合にメモリーのハンドルが必要になって GMEM_MOVEABLE 属性で
GlobalAlloc API を使ったことがある程度です

私なりの結論---まとめ---です
GMEM_MOVEABLE ではメモリーハンドルが返るのでハンドルが必要な場合
GMEM_FIXED ではハンドルではなく番地が返るのでハンドルが不要な場合
にそれぞれ使うといいでしょう
ただ、メモリーハンドルにはハンドル数の上限があるので使いすぎに注意しましょう?!
(もっとも、使いすぎる位になるとしたら別途マネージャーを用意するだろうから
余り意味の無い注意かもしれない)

以下、余談です
GMEM_MOVEABLE は Win16 の時代には Win32 の様なページングによる仮想記憶では
なかったので限られた使用可能な番地の範囲を有効利用するために必要な技巧では
あったかも知れませんが、1Gバイトだとか2Gバイトだとかの仮想記憶空間が使える
Win32 では余り真剣に使い分けを考えることは無いのではないかと感じています
メモリーハンドルが必要かどうかで使い分ければいいのではないでしょうか


返信引用
ku
 ku
(@ku)
ゲスト
結合: 24年前
投稿: 312
 

>固定メモリと、移動可能メモリは違うのでしょうか?
違います。

>そして、それらの使い道を教えてください。
クリップボード関係など、GMEM_MOVEABLEで確保したハンドルを
渡さなければならないAPIには
GlobalAlloc(GMEM_MOVEABLE, )で得たハンドルを渡す
そうでなければGMEM_FIXEDかmalloc()/new等を使用する

HGLOBAL h = GlobalAlloc(GMEM_MOVEABLE, 100);
if (h) {
unsigned long* p1 = (unsigned long*)h;
unsigned long* p2 = (unsigned long*)GlobalLock(h);
こんなプログラムを動かしてみると
*p1とp2は同じ値となる
(たまたま同じ値になると考えるべきなのでp1を使用してはいけません)

とはいえ、もう少し考察を続けると
GlobalAlloc(GMEM_MOVEABLE, )で得られる値は実は仮想空間のアドレスである
GlobalAlloc(GMEM_MOVEABLE, )で得られた値をunsigned long*にキャストすると
GlobalLock()した値と同じ値を得ることが出来る
これはGlobalAlloc(GMEM_MOVEABLE, )した時点でGlobalLock()したときに
得られる仮想アドレスが決定していることを示している
おまけだけど、GlobalAlloc(GMEM_MOVEABLE, )で得られた値を仮想アドレスとした場合
その2バイト前がロックカウントではないかと考えられる

現在ではクリップボード関係やマルチメディア系(使ったことないので良くわからない)
のAPIにGlobalAlloc(GMEM_MOVEABLE, )で得られるHGLOBALを渡さないといけないものがあり
これらについては移動可能なメモリのハンドルを渡さないといけない
しかし理由がない限りGMEM_FIXEDを使った方が良いような事を本で読んだことがあります
Win32では物理的なアドレスはVirtualAlloc()等を使用して固定化するのだと思うけど
(こちらも使ったことないので正確でないかもしれません)
Win16ではGlobalLock()でも物理アドレスを固定化できました
(VirtualAllocのように希望する物理アドレスを指定することは当然できません)
逆説的には物理メモリからスワップしても構わないとOSに伝えるために
GlobalUnlock()を呼んであげるのが流儀でした
Win16ではGlobalLock()->GlobalUnlock()->GlobalLock()するたびに違うアドレスが
返されることは良くあったのだと思います

なおGMEM_MOVEABLEを必要なとき以外使用しない法がよい理由はWin32で利用できる
移動可能なメモリブロックの数が65535個だからだそうである
(95系かNT系か両方か、どれについて言及しているのか分かりません)

※動作の確認にはWindows2000を使用しました


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました