none
Windows 7+ワイドディスプレイ+ディスプレイ色設定(32bit)でCreateDIBSection()が失敗してしまう。 RRS feed

  • 質問

  • はじめまして。

    Windows XP+Visal Stadio 2005(VC++)で作成したプログラム(CAD)にて
    CreateDIBSection()を使用していました。

    このプログラムを
    Windows 7 Professional(SP1)+Visal Stadio 2005でビルドし、
    スクエアなディスプレイ(解像度1280×1024)で動かすと
    CreateDIBSection()は成功するのですが、
    ワイドディスプレイ(解像度1680×1050)で動かすと
    CreateDIBSection()が失敗してしまいます。
    GetLastError()で失敗理由を調査したところ
    8:ERROR_NOT_ENOUGH_MEMORYでした。

    ちなみに
    Windows 7のディスプレイのプロパティで
    色設定をTruecolor(32bit)からHighcolor(16bit)に変更すると
    CreateDIBSection()は正常動作します。

    或いは、Truecolor(32bit)でもWindowsのテーマをクラシックに
    変更してもCreateDIBSection()は正常動作します。

    Windows 7+ワイドディスプレイ+ディスプレイ色設定(32bit)で
    CreateDIBSection()が失敗する原因はVRAMの空き不足でしょうか?
    それともメインメモリ(RAM)においてCreateDIBSection()の要求する領域を
    連続メモリ領域として確保できないためでしょうか?

    <補足>

    ・マシンスペック
     メモリ(RAM)=4G (3.4GB使用可能)
      ディスプレイアダプタのグラフィックメモリ(VRAM)=1551MB

    ・CreateDIBSection()の第二引数(BITMAPINFO構造体)のbmiHeader.biWidthとbiHeightには
     画面縦横サイズのそれぞれを3倍したサイズを設定しています。
     (スクエアなディスプレイだろうが、ワイドディスプレイを使用しようが
      RAM及びVRAMにおいて十分な空きはあります)

    ・CreateDIBSection()の第三引数(iUsage)はDIB_RGB_COLORSを指定しています。
    ・CreateDIBSection()が失敗する際、Office等余計なプリケーションは一切動作させてはいません。
     (McAfeeが常駐している程度です)

    2014年8月13日 7:30

回答

  • 原因ははっきりしたようですが思ってた以上にメモリ使ってる状態っぽいかな・・・。

    少し程度なら設定や最適化オプションで空くかもしれませんが、コードの大幅修正がないと MB 単位で空けるのは難しいのじゃないかな?

    jzkey 様のおっしゃる内容での対応が一番とは思います。 「CADのモジュール」が DLL で原因なら配置固めとか、まとめてしまうとか、64bit OS で 32bit アプリを動作させる場合に仮想メモリのユーザー領域を拡張する指定ですね。

    今後 64bit 化か全面改修を考えないといけない感じなので、64bit OS 対応で現状ユーザーに我慢してもらえれば良いですけどね・・・・。

    さて、

    リークを除いたコーディングによる断片化が要因ならば通常はヒープの確保解放順序の問題になると思われます。

    2個確保した領域の<先行確保>領域を解放すると断片化となる理屈で new & delete も確か同じ考えが必要です、関数コールで確保したメモリ解放のタイミングが断片化の要因になりやすいですね。※解放した領域は小さいサイズでなら再割付できますが、端数が残る可能性が高いですよね?

    よって、大きくて解放しないメモリから確保するのが良いのですが意外と簡単にはいきません・・・。

    今回の CreateDIBSection もでしたが API もヒープ確保する場合があるので、ハンドル取得と解放のタイミングは気にする必要があるはずです。

    後、マルチスレッドの場合も確保と解放のタイミングが問題になったんじゃなかったかな?(メモリに余裕があると思って意識した事はほぼないけど・・・)

    よって、繋げれば 60 MB を越える領域があるのなら、間をふさぐメモリ確保コードを探し出せれば、処理タイミング変更等でなんとかならないか試すのも手段ではあるけど、望みが薄い割に手間がかかると思います。

    ~~~~~~~~~~~~

    <先行確保>のところを<上位>としてました。 <下位>と書くべきところで<上位>って意味不明になる・・・。

    ついでなのでわかり易いかなと思う表現に変更・・・。

    • 回答としてマーク 長峰 2015年7月10日 0:30
    • 編集済み kyano30 2015年7月10日 16:17 間違い修正
    2014年8月29日 11:25

すべての返信

  • 原因はそこなのでしょうか? こちらで次のコードを試してみたところ

    HDC hdc = GetDC(0);
    BITMAPINFO bitmapInfo = { { sizeof BITMAPINFOHEADER, 1680 * 15, 1050 * 15, 1, 32, BI_RGB } };
    void* bits;
    HBITMAP bitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, 0, 0);
    
    1.5GBくらいまでは成功しました。

    # メインメモリ2GBのマシンです。

    パラメーターに問題があったり、他の処理でメモリが断片化してるなどはありませんか?

    • 回答の候補に設定 佐祐理 2014年8月26日 10:57
    2014年8月13日 8:39
  • CreateDIBSection()の呼び出し前にSetLastError(0)を実行した場合はどうなりますか?

    GetLastError()が別のAPI呼び出しのエラーコードを保持したままという可能性はありませんか?

    CreateDIBSection()自体はオフスクリーンのシステムメモリにDIBを確保し、これはDirect3Dのスワップチェーンとは関わらないので、VRAMは関係ないはずです。

    ちなみにグラフィックスメモリというのはグラフィックスカード搭載の専用メモリですか? それともモバイルやCPU内蔵GPUなどの共有メモリですか?

    2014年8月13日 17:42
  • sygh 様が指摘しててますけど DIB はシステム側に領域をとるものだった気がするので、症状からするとシステムメモリ部の空き領域不足ではないかと思いましたが・・・。

    OS のバージョンは 64bit 版でしょうか? 32bit 版だからなのでは?という気がします。

    1680x1050 の 3x3 倍サイズの DIB は大き過ぎるとは思いませんけど、Win7 32bit OS のシステム領域内に確保されると考えるなら、やや大きいサイズに思えるので・・・。

    ※(3.4GB使用可能)という表記から 32bit 版のシステム表示?と思って疑ったのですけど、32bit 環境ないので佐祐理様の確保のみコードも試してません・・・

    2014年8月13日 20:26
  • ■sygh様

    >CreateDIBSection()の呼び出し前にSetLastError(0)を実行した場合はどうなりますか?

    上記を行ったのですが、
    やはりCreateDIBSection()直後のGetLastError()で
    8:ERROR_NOT_ENOUGH_MEMORYになってしまいます。

    で、ディスプレイのプロパティより
    色設定をTruecolor(32bit)からHighcolor(16bit)に変更すると
    CreateDIBSection()直後のGetLastError()では
    0(NO_ERROR)となります。


    >グラフィックスメモリというのはグラフィックスカード搭載の専用メモリですか?
    >それともモバイルやCPU内蔵GPUなどの共有メモリですか?

    グラフィックスカード搭載の専用メモリです。

    ディスプレイのプロパティ
    (デスクトップで右クリック→個人設定→ディスプレイ→ディスプレイの設定変更→詳細設定)
    で確認すると以下となっております。

    ・チップの種類:Intel(R) HD Graphics Family
    ・アダプター文字列:Intel HD Graphics 2500

    ・利用可能な全グラフィックスメモリ:1551 MB
    ・専用ビデオメモリ:64MB
    ・システムビデオメモリ:0 MB
    ・共有システムメモリ:1487 MB

    ■kyano30様

    >OS のバージョンは 64bit 版でしょうか?
    >32bit 版だからなのでは?という気がします。
    >※(3.4GB使用可能)という表記から

    OS のバージョンは 32bit 版です。

    >1680x1050 の 3x3 倍サイズの DIB は大き過ぎるとは思いませんけど、
    >Win7 32bit OS のシステム領域内に確保されると考えるなら、
    >やや大きいサイズに思えるので・・・

    色設定がTruecolor(32bit)時の
    1680x1050 の 3x3 倍サイズの DIBサイズは
    (1680×3)×(1050×3)×32bit/8byte = 約60.6MBなのでしょうか?
    この程度のサイズだとしても、メモリが逼迫しているとも思えないのですが・・・

    ■佐祐理様

    >他の処理でメモリが断片化してるなどはありませんか?

    フリーのソフトでそのような確認ができるのもがないか
    探してみます・・・

    2014年8月14日 4:14
  • >他の処理でメモリが断片化してるなどはありませんか?

    フリーのソフトでそのような確認ができるのもがないか
    探してみます・・・

    そうではなく、新規にコンソールアプリケーションプロジェクトを作成し、main()内に先に挙げた4行だけを記述し実行した場合に、HBITMAPが得られるかを確認してみてください。成功するのであれば、CreateDIBSection()は原因ではなく、プログラムの他の部分の問題でしょう。
    2014年8月14日 4:20
  • 提示されたスペックを見る限り、グラフィックスチップはオンボードもしくはCPU内蔵のもので、グラフィックス専用メモリ(GPU直結メモリ)は1551MBではなく64MBでしょう。1551MBという表記はシステムメモリ上の共有部分1487MBと専用メモリ64MBの和で、Intel HD Graphicsの場合、共有メモリに関してはアプリケーションに応じてシステムから最適なメモリ容量が動的に割り当てられるそうです。

    ちなみに、(デスクトップ解像度にもよりますが)Windows VistaのAero動作必須要件はVRAM 128MBで、おそらくWindows 7のAeroも(明記はされていませんが)それに準ずるはずのため、専用メモリに関してのみ着目するならばAeroの必須動作環境を満たしていないように思われます。Windows Vista/7ではAeroをONにしたときのみDWMが有効になり、デスクトップ領域に対応したDirect3Dバックバッファが確保されるようになります。また、DWM合成に必要となる、各アプリケーションのウィンドウサイズに応じたテクスチャメモリも確保されます。

    http://news.mynavi.jp/special/2009/windows7/032.html

    ただ、16bitカラーにしたり、クラシックテーマにしたりするとアプリ(CreateDIBSection() API)が動作する、というのは、確保すべきDirect3Dバックバッファやテクスチャの容量が減ってシステム全体の負荷が軽くなることが関与しているものかと思われます。前述のとおりCreateDIBSection()自体はVRAMにメモリを確保するものではありませんが、CreateDIBSection()が内部でシステムの状態をどのようにチェックしてメモリが不足していると判断しているのかは知るすべがありません。

    ちなみに似たような過去スレッドがありました。

    CreateDIBSection で大きいビットマップを作るとエラーになる場合がある。

    こちらは断片化が原因ではないかということで結論付けられたようですが、本当の原因はちょっと違うような気がします……

    • 編集済み sygh 2014年8月14日 6:59
    2014年8月14日 5:09
  • 今の状況では回答側は推測をいろいろとするしかなく、発散すると思われます。
    再現できるサンプルソースコード、あるいは差し障りない形で抽出した実際のソースコードを提示できないでしょうか。
    (業務で開発しているソースコードの場合、そのまま転載すると情報漏洩に該当する可能性があります。ご注意ください)

    なお、メモリの断片化についてみたい場合は VMMap がよいかと。

    2014年8月14日 10:01
    モデレータ
  • 完全な憶測なので返信するのもなんなのですけど・・・。

    > (1680×3)×(1050×3)×32bit/8byte = 約60.6MBなのでしょうか?

    恐らくはその程度のサイズで間違ってないのではないかと思います。

    32bit 版のシステム領域は仮想的には 2GB ですが、システム要件等から想像するとおそらく 500MB 程度なんじゃないかと思ってます。

    500MB 中にカーネル領域もあるはずで、それを考慮すると使える領域は 200MB もあるかどうか?と考えてますが、あくまで憶測です・・・。

    ※システムメモリ上の共有部分は利用しないって考えですね。

    200MB 程度から 60MB の連続領域と考えるなら大きいでしょ?という風に思ってますけど、環境もないし裏付けとなる情報皆無で信用されても困るという・・・・。

    2014年8月14日 12:40
  • ■Azulean様

    >業務で開発しているソースコードの場合、そのまま転載すると
    >情報漏洩に該当する可能性があります。ご注意ください

    本ソースコードは、ある企業向けCADのソースコード
    (15年くらい前に開発したパッケージ)なのですが、
    STEP数が膨大であるため、抽出はなかなか難しいです。
    ただエッセンスとしては佐祐理様が記述された4行のコードです。


    ・以下のようにデバイスコンテキストのハンドル(第一引数)2種類(業務ロジックの都合上)
     にて、それぞれCreateDIBSection()をCALLしています。

     CreateDIBSection(hdc1,&bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0)
     ~
     CreateDIBSection(hdc2,&bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0)
     

    ・解像度(縦・横)のそれぞれ3倍の領域をbmiHeader.biWidthとbiHeightと
     していると記述しましたが、実際にはCADを操作するためのコマンド群を
     配置したりするエリアがあるので、それらを除いた、CAD要素(線分等の幾何要素)の
     描画用領域をCreateDIBSection()で確保しています。
     (解像度(縦・横)の約7割程度のサイズをそれぞれ3倍した領域を設定)


    <余談>

    ・解像度(縦・横)のそれぞれ3倍の領域を設定している理由ですが
     カレント画面を中心として、上下左右方向それぞれに
     1画面分のスクロールを行った際に、幾何要素を再描画させることなく
     スムーズにスクロール移動させるため。

    ・マシンの使われ方次第(様々な業務アプリやOffice等の立ち上げ/終了の繰り返し加減)では
     1回目のCreateDIBSection()で失敗する場合もあり、
     2回目のCreateDIBSection()で失敗する場合もあります。

    ・CreateDIBSection()が失敗した場合、画面をスクロールさせると、
     描画させていた図形要素が(ソリティアの終了画面のように)残像を
     起こしてしまいます。(これが本フォーラムに投稿するキッカケです)

    ・Win7でワイドディスプレイを使用しているユーザ様には
     以下をアナウンスしています。  

      ・解像度(縦・横)のそれぞれ3倍固定でなく、2~3倍の範囲で
       スクロール領域を設定可能なように、この値を設定できるUIを急遽提供し
       (且つこの倍率でCreateDIBSection()に設定)、ユーザ様に任意に設定して頂く。
       (この値を下げてもCreateDIBSection()が成功する率が向上する)

      ・色設定をTruecolor(32bit)をHighcolor(16bit)にする or Windowsのテーマを
       クラシックにする。

    >なお、メモリの断片化についてみたい場合は VMMap がよいかと。

    ありがとうござます。あとで使ってみます。

    ■kyano30様

    >200MB 程度から 60MB の連続領域と考えるなら大きいでしょ?という風に思ってますけど、
    >環境もないし裏付けとなる情報皆無で信用されても困るという・・・・。

    ・実際には本業務ソフトを起動時には、いつくかのDLLをリンクしたり
     マスタを読み込んだりするので、CreateDIBSection()直前くらいまでは
     約180MBくらいメモリを使います。

    ・そこからさらにCreateDIBSection()を2回行うので、
     1回につき約60MBとして、2回で約120MBです。

    メモリの連続領域にも起因?となるとAzulean様に
    提示頂いたVMMapで確認してみます。

    ■sygh様

    >Direct3Dバックバッファやテクスチャの容量が減って
    >システム全体の負荷が軽くなることが関与しているものかと思われます。

    なるほど、非常に気になる内容です。
    研究してみます。

    >ちなみに似たような過去スレッドがありました。
    >CreateDIBSection で大きいビットマップを作るとエラーになる場合がある。

    はい。
    本スレッド投稿する前に、上記過去スレッドは拝見していました。


    ■佐祐理 様

    >そうではなく、新規にコンソールアプリケーションプロジェクトを作成し、
    >main()内に先に挙げた4行だけを記述し実行した場合に、HBITMAPが得られるかを
    >確認してみてください。

    提示頂いた4行ソースコードだけを記述したプロジェクトでは
    TrueColor(32bit)時、1680 * 1050のそれぞれ14倍でHBITMAPは
    NULLになります。
    HighColor(16bit)に切り替えたら成功するのか試してみたのですが
    失敗しました・・・

    >成功するのであれば、CreateDIBSection()は原因ではなく、
    >プログラムの他の部分の問題でしょう。

    たしかにプログラムの他の部分の問題にあるような気もするのですが、

    >CreateDIBSection()が内部でシステムの状態を
    >どのようにチェックしてメモリが不足していると判断しているのかは
    >知るすべがありません。

    とsugn様も記述されている通り、
    なかなか他箇所の問題特定も厳しいかな、と思っております。

    今のところ前述したユーザ様へのアナウンス内容で
    100%回避でてきているので、やはりCreateDIBSection()の内部で
    どうチェックしているかですね。
    (結局、この中がブラックボックスなので…)

    2014年8月15日 10:39
  • ここから書くことは予想に過ぎませんので、VMMap など、メモリ使用状況を可視化して、状況を確認していただく必要があります。

    ディスプレイのプロパティの True Color/High Color の設定に応じてメモリを使用する部分が現在のプログラムのどこかに存在する。
    それによって、CreateDIBSection が連続したメモリを確保できる・できないの状況を作り出しているのではないか?

    このように予想するのは、長峰さんが「コンソールアプリでは成功する」「コンソールアプリの場合、True Color/High Color の設定の影響を受けない」という実験をされており、CreateDIBSection 周りのソースコードも佐祐理さんが示したものとほぼ同等ということからです。
    つまり、「CreateDIBSection は悪くない」、「CreateDIBSection が処理できない状況を作り出している」という予想です。

    もっとも、確たる証拠があるわけでもないので、VMMap などで観測していただくのが原因特定の近道だと思います。
    メモリが十分確保できるのであれば、前述の予想はハズレです。

    2014年8月15日 10:43
    モデレータ
  • 提示頂いた4行ソースコードだけを記述したプロジェクトではTrueColor(32bit)時、1680 * 1050のそれぞれ14倍でHBITMAPはNULLになります。

    Azuleanさんの繰り返しになりますが、当初は画面サイズの3倍(約60MB)が確保できないという問題でしたが、私の提示したコードであれば13倍(約1137MB)まで確保できるのであれば、話が違ってきませんか?
    # という点は私が当初より指摘しています。

    VMMapなどアドバイスがありますが、そもそも1プロセスで2GB使用可能な状況に於いて60MB程度の連続領域が確保できないというのもおかしな話です。
    試しにCreateDIBSectionがエラーを返す状況でmalloc()で同サイズを確保してみてください。確保に成功するのであればメモリ不足が原因ではなく他のリソース不足でしょう。メモリ確保に失敗するのであれば…まぁメモリリークですが…とはいえどちらにしてもCreateDIBSection()の問題ではないでしょう。

    • 回答の候補に設定 星 睦美 2014年8月18日 5:18
    2014年8月15日 11:53
  • う~ん、完全に外してしまって申し訳ないので、64bit OS 環境ですが少し調べてみました。

    VMMap で確認してみたところ CreateDIBSection で確保されるメモリはユーザー領域に確保されるようで、画面サイズの3倍で確保する場合、約62MB になるようです。※よって自分の推測は完全に見当違いです。

    なので CAD らしいので、色々メモリ確保して断片化はしてるでしょうし連続領域の不足という可能性が高いですかね。

    とはいえ、ほぼ空の Win32 アプリで連続領域は 1.5 GB 程度空いてますし、領域間も 100 MB 程度が開いてたりするので 180 + 60 x 2 = 300MB 程度が主要なメモリ利用なら空きがないほどというのは想像しにくいですけど・・・。

    佐祐理様が指摘してるように malloc で同サイズの確保ができないか?というのを実行ソース内で調べてみるのも良いと思います。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    余談ですが、佐祐理様の例示コードを Win32 テスト用プロジェクトのメッセージループ前に追加して確認したところ、一度は確保できたのに2回目から失敗、14倍はとれたりとれなかったり・・・。

    Thread Stack の配置に邪魔されてるんですが、 サイズが 1.5GB とユーザー領域の大半をしめる条件なので 60 MB 程度を失敗するのとは関係ないでしょうね・・・・。

    2014年8月15日 15:29
  • ■Azulean様/佐祐理様/kyano30様

    アドバイスありがとうございます。

    >試しにCreateDIBSectionがエラーを返す状況で
    >malloc()で同サイズを確保してみてください。

    来週1Wは夏季休暇を取るので、次回出社する8/25以降に
    VMMap、及び上記を試してみます。

    2014年8月16日 15:32
  • >試しにCreateDIBSectionがエラーを返す状況でmalloc()で
    >同サイズを確保してみてください。


    malloc()が失敗しました。
    よってメモリの断片化が起きていると思われます。

    ただ失敗時、リソースモニターやRamMapでメモリの空きサイズを確認したところ、
    260MBくらいあったので、60MB程の連続領域を確保できないのは
    いまひとつ解せませんが・・・。(この空き領域が断片化しているのでしょうか)

    ちなみにVMMapで確認したところ、
    CreateDIBSectionで確保されるメモリ領域としては
    malloc()と同様、プライベートデータ(Private Data)でした。

    2014年8月26日 9:46
  • 最初のコメントの通りでしたね。

    通常は1500MBは確保できる状態ですから、1240MB位のメモリが確保されたまま解放されずにいることになります。メモリ解放されていない個所を探して修正しましょう。

    2014年8月26日 11:00
  • > ただ失敗時、リソースモニターやRamMapでメモリの空きサイズを確認したところ、

    一応、そちらは物理メモリの利用状況をみるツール類のはずで、プロセス毎の仮想メモリ空間をみるのが VMMap ですね。

    32bit アプリは 4GB の仮想メモリ空間の下位 2GB のアドレス領域がユーザーが利用可能となり、一応は物理メモリのアドレス空間とは切り離して考える事になります。

    ※32bit OSで使える物理メモリは 4GB までなのに、複数アプリが仮想メモリ空間を持つのは結構不思議ですけど・・・。

    VMMap で連続領域を確認するとなると、メニュー [Options]-[Show Free and Unusable Region] にチェックをいれて Free のSize が空いている連続領域のはずです。

    ※Unusable 部は利用できない領域と思われ 確保メモリサイズより少し大きい領域が占有されるとか、どこかに書かれてたはず・・・。

    たぶん思ってるよりは断片化されてると思いますが VMMap で空いている連続領域は十分でしたか?

    仮想メモリが十分に空いているなら物理メモリ側の問題もあるのかも知れませんけど・・・。

    2014年8月26日 11:47
  • kyano30 様、佐祐理 様

    >たぶん思ってるよりは断片化されてると思いますが
    >VMMap で空いている連続領域は十分でしたか?

    空き領域は大体60個くらいに断片化されていました。
    連続領域としての最大は62Mで、次に大きいのが40Mくらいでした。

    CreateDIBSection()は2回実行している、と以前記述しましたが、
    ディスプレイの色をTruecolor(32bit) 且つ
    1680x1050 の 3x3 倍サイズの DIBサイズ(約60MB)として、
    1回目のCreateDIBSection()は成功し、2回目の
    CreateDIBSection()が失敗する理由は
    まさに2回目で連続領域が取れないからですね。

    ディスプレイの色をHighColor(16bit)にするとDIBサイズが
    半分の約30MBになるので、2回目のCreateDIBSection()も
    余裕で成功します。

    >メモリ解放されていない個所を探して修正しましょう。

    VMMapで、CreateDIBSection()の直前までの
    メモリ先頭アドレスから割り当て状況を確認したところ、
    OS系(C:\Windows\system32\~.dll等)が約100本、CADのモジュール群が
    約400本と合計500くらいのモジュールが割り当てられていました。

    コツコツと開放漏れを探して修正しても、結局は
    空き領域は断片化されたままとなっている可能性がありますよね・・・
    (大量、且つ過去のアプリ資産なので今更探す気にもなれない)

    空の連続領域を大きく確保し、且つなるべく断片化させないような技法
    (OSの何らかの設定、プロジェクトのビルド時のスイッチや
     プログラミング時の考慮点)として何かあるものでしょうか?

    何か改良ポイントがなさそうであれば、ユーザに状況を説明し
    本件クローズしてしまおうかとも思っています。

    2014年8月28日 9:47
  • その「CADのモジュール」というのが、DLLのコードのことであれば、(断片化の主犯であれば)、DLLをリベースして仮想メモリ中の場所を固める手はあると思います。

    あとは、EXEにLARGEADDRESSAWAREをつけて、「64bitOSで動かしてください」と言えば、仮想メモリは4GBまで増えますけどね、


    jzkey

    2014年8月28日 14:14
  • 断片化と表現しましたが、大抵の場合は単なるメモリ解放漏れ(メモリリーク)が原因です。それを「改良ポイントがな」いと表現するのは自由ですが、もし本当に1GB以上を要するアプリケーションであれば64bit化すべきでしょう。

    2014年8月28日 15:00
  • 原因ははっきりしたようですが思ってた以上にメモリ使ってる状態っぽいかな・・・。

    少し程度なら設定や最適化オプションで空くかもしれませんが、コードの大幅修正がないと MB 単位で空けるのは難しいのじゃないかな?

    jzkey 様のおっしゃる内容での対応が一番とは思います。 「CADのモジュール」が DLL で原因なら配置固めとか、まとめてしまうとか、64bit OS で 32bit アプリを動作させる場合に仮想メモリのユーザー領域を拡張する指定ですね。

    今後 64bit 化か全面改修を考えないといけない感じなので、64bit OS 対応で現状ユーザーに我慢してもらえれば良いですけどね・・・・。

    さて、

    リークを除いたコーディングによる断片化が要因ならば通常はヒープの確保解放順序の問題になると思われます。

    2個確保した領域の<先行確保>領域を解放すると断片化となる理屈で new & delete も確か同じ考えが必要です、関数コールで確保したメモリ解放のタイミングが断片化の要因になりやすいですね。※解放した領域は小さいサイズでなら再割付できますが、端数が残る可能性が高いですよね?

    よって、大きくて解放しないメモリから確保するのが良いのですが意外と簡単にはいきません・・・。

    今回の CreateDIBSection もでしたが API もヒープ確保する場合があるので、ハンドル取得と解放のタイミングは気にする必要があるはずです。

    後、マルチスレッドの場合も確保と解放のタイミングが問題になったんじゃなかったかな?(メモリに余裕があると思って意識した事はほぼないけど・・・)

    よって、繋げれば 60 MB を越える領域があるのなら、間をふさぐメモリ確保コードを探し出せれば、処理タイミング変更等でなんとかならないか試すのも手段ではあるけど、望みが薄い割に手間がかかると思います。

    ~~~~~~~~~~~~

    <先行確保>のところを<上位>としてました。 <下位>と書くべきところで<上位>って意味不明になる・・・。

    ついでなのでわかり易いかなと思う表現に変更・・・。

    • 回答としてマーク 長峰 2015年7月10日 0:30
    • 編集済み kyano30 2015年7月10日 16:17 間違い修正
    2014年8月29日 11:25