• 締切済み

GUIアプリケーションで連続領域がとれません。

WinXP上でVC6.1SP6を使用しGUIアプリケーションを作成しています。 WinMainの直下で下記を実行してもNULLが戻ります。 char *p; p=malloc(0x65000000);  ちなみにConsoleアプリの場合main直下で同じ処理が正常に動作します。  2分探索で確保出来る領域を調べるとGUIアプリの場合、mallocで確保されるフリーアドレス空間が分断されているように思われます。  WinMain直下での現象ですので、OSのバッグとしか考えられないのですが、なにか回避法はないものでしょうか?  W2kでも最大空きブロックのサイズは違いますが、同じ現象が確認できました。

みんなの回答

  • terra5
  • ベストアンサー率34% (574/1662)
回答No.4

ConsoleとWindowsアプリではスタートアップも違うでしょうから、十分ありえると思いますが。 リンクしているライブラリも違えば、プログラムサイズも違うでしょうし、ヒープ領域サイズ、スタックサイズ等もどうなっているかわかりませんし。 あと、DLLの動きもからんでくるでしょう。 APIもGUIに限りませんし。 原因をはっきりさせたいなら、やはり最低でもスタートアップの処理を追うしかないでしょうし、 上記の内容もチェックする必要があると思います。 多分、全部は追いきれないと思いますが。 普通はOSが何であるかにかかわらずそんな大きな連続領域を必要とするようなプログラムが問題として対応すると思いますが。 実際動作しないわけですから。 逆にどうしても必要なら、はじめからそれ相応の対処、準備、環境の選択を行うべきでしょうし。

msykykt
質問者

お礼

たびたびのレスをいただき恐縮です。 結局MSのサポートを受けて問題は解決いたしました。 ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.3

>知りたいのは、この現象はWinプログラマーの皆さんには一般的に知れ渡っている物なのかと言うことなんです。 ANSIでは mallocで確保できない場合はNULL、0、あるいはそれを表すポインタが返ってくるとになっています。 普通のプログラマは知っているでしょう。mallocの説明をみればそう記述してあるはずです。 メモリの断片化がおきるのはGUI関連かどうかは関係ありません。 linuxだろうがMacOSだろうが長時間使えばメモリは断片化します。 APIのHeapAllocを使ってみてください。 恐らくSTATUS_NO_MEMORYのエラーが返ると思います。 Windowsの場合mallocも結局は内部でAPIのHeapAllocを呼んでいます。 0x65000000が尋常ではない値なのです。 そもそもWin2000ProではOS自体4Gバイト以上のメモリを扱えないですし、 その1/3の値を連続領域でとろうとしても普通は確保できないでしょう。

全文を見る
すると、全ての回答が全文表示されます。
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

リリースモードでビルドしてもですか? あと自分でスタートアップルーチンを自分で見てみてはいかがでしょうか? VC6++でしたらCRT0.Cです。ソースついてるんですから疑う前に確認しましょう。 あとは、それでも上手くいかないようでしたらスタートアップルーチン自分で空のを書いちゃえばいいかと。ランタイム関数は使えなくなるんでメモリ確保はHeapAlloc()とかになりますが。

全文を見る
すると、全ての回答が全文表示されます。
  • terra5
  • ベストアンサー率34% (574/1662)
回答No.1

GUIを使うと細かいメモリアロケートと開放が大分発生すると思いますので、 分断化はしかたない現象と思いますが。 それより連続領域で約1.6GByteもとるプログラムをなんとかすべきでしょう。 データ構造とかメモリ確保の方法とかアルゴリズムに問題があるのでは? まともに動かすには物理メモリどれぐらい必要でしょうね。 どうしてもというのであれば、Consoleだと取れるということなら、 処理はconsoleのプロセスで行い、インターフェイス部だけWinMainにもっていていって、なんらかのプロセス間通信で処理することになると思いますが。

msykykt
質問者

補足

terra5様、質問にご回答いただきありがとうございます。  どうも言葉が足りなかった様で申し訳ありません。  知りたいのは、この現象はWinプログラマーの皆さんには一般的に知れ渡っている物なのかと言うことなんです。  1.6Gというのは、検証用として記載したもので、実際のプログラムではご指摘の様な方法で対処は可能かと思います。  ただそのために、開発のコストがかさむので、この現象が既知で有ることを示す必要があり、質問をさせていただいた次第です。  一点気になるのですが、ご指摘の「細分化が発生する」のはGUI関連のAPIを使用していく過程での事ではないですか?  その現象であれば理解できるのですが問題は、WinMain直後(直下では無いですね)で起きています。  テスト作業はVCで新規にWin32Applicationを選び「標準的なHelloWorldアプリケーション」を作成して下記の様に3行追加しただけです。 ----- from here --------- int APIENTRY WinMain(HINSTANCE hInstance,... { MSG msg; HACCEL hAccelTable; char *p; p=(char *)malloc(0x65000000); if(p==NULL) exit(1); ------ to here ------  つまり何も処理を行っていない時点での話しですの、crt0.objの中で行われているであろう初期化処理を疑っている訳です。  仰っている細分化が、この現象のことで有れば万々歳なのですが、どうなのでしょうか。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 文字型配列の有効期間

     char 型配列の有効期間について教えてください。 例えば、 char* p=(char*)malloc(sizeof(char)*10) などで、動的に配列を確保した場合、必ずfree()で、 開放する必要があると思うのですが、 char[]="Hello"; char* p; p=char; p=null; char=null; とした場合、pとcharが指していた”Hello"の領域は 自動的に開放されるのでしょうか?また、開放される としたらそれは、pおよびcharにnull が代入された 時点でしょうか? どうぞよろしくお願いいたします。

  • メモリ確保エラー時の効率的な書き方

    mallocなどで複数の変数に対してメモリを確保する場合があると思います.例えば3つの変数の場合, char *a, *b, *c; a = (char *)malloc(100); if(a==NULL){ /* メモリ確保できなかったとき */ return (-1); } b = (char *)malloc(100); if(b==NULL){ free(a); return (-1); } c = (char *)malloc(100); if(c==NULL){ free(a); free(b); return (-1); } 変数が多くなるにつれて後から確保する変数のエラー処理(すでに確保したメモリのfree)が増えてしまうので,何か良い方法(コードが短くなるような)はないでしょうか?

  • 領域の確保について

    callocやmallocで領域の確保が出来ると思いますが、領域が確保できなかったりする事があると思います。 char test[100000]; とか配列を宣言した場合も領域が確保されると思いますが、 これは確保する事が出来ない事とかはあるのでしょうか? また確保できなかった場合はどうなるのでしょうか? すいません、なんか勘違いしているかも知れませんが、宜しくお願いします。

  • mallocでメモリーを確保しようとすると暴走します

     組み込み系のプログラミングをやっているもので、malloc、freeを使って動的にメモリーの確保、開放を行っているのですが、途中で暴走してしまいます。 (mallocを呼び出すと、返ってこなくなります。)    そこでmallocの動作を見ようと、以下のプログラムを作って動作させると、while文の中を一周はするのですが、2週目のp2のポインターの値が返ってきません。(malloc関数の中でloopしています。)     /* 以下ソースコード */  char *p1;  char *p2;  char *p3;  char *p4;  while(1){    p1 = (char*)malloc(100);    p2 = (char*)malloc(100);    p3 = (char*)malloc(100);    free(p3);    p4 = (char*)malloc(100);    free(p4);    free(p2);    free(p1);  }  ※メモリーは、2k確保していあるので、サイズがオーバーしているということはないと思います。  ご質問ですが、  ・上記ソースコードで暴走するような要因がありますでしょうか?  ・malloc、free関数でメモリーの取得、開放の順番など注意しないといけないことがあるのでしょうか?  ・malloc、free関数等を自作とかされていますでしょうか?  どうぞよろしくお願い致します。

  • C言語 動的なメモリの確保 実行できない

    malloc関数を使いメモリを確保しそこへ"ABCD"と記憶させ、ポインタ*Cを使い確保したメモリの内容を表示するプログラムです。 ********************************************* #include <stdio.h> #include <stdlib.h> int main(void) {   int i;   char *C;   C = (char *) malloc (sizeof(char) * 5);   C = "ABCD";   for(i = 0; i < 5; i++){     if(C[i] != NULL){       printf("%s", C[i]);    ←※エラー※     }   }   free(C);   return 0; } ********************************************* 正常にコンパイルできますが実行エラーになります。VCを使いF10のデバッグテストで※のところエラーになります。なぜなのでしょうか?

  • メモリ

    メモリについてご質問します。 例えば char *p; p = (char *)malloc(100); とすればpに100バイトのメモリが割り当てられる・・ pに文字列を代入する場合100バイトまで格納可能である。 次にファイルからの一行のある部分の文字列を入れる場合 char *s; while(fgets(buf,1000,fp) !=NULL){ s = GetWord(・・)//何らかの文字列が返ってくる関数です とする場合このときのsについてもメモリを取得しなければなりません。 その際 s = (char *)malloc(100); while(/*省略*/){ とwhileの外でとるのか、それとも while(/*省略*/){ s = (char *)malloc(100); と中でとるべきなのかどっちでしょう? というのもwhile文の中でメモリを作成すると 1回ごとに新たなメモリをとっているのか 更新されていっているのかがわかりません。

  • char型ポインタ

    よくプログラムで charポインタだけ指定して、 #include<stdio.h> int main(){ char* p; p = "abcdef"; printf("%s",p); return 0; } のようにしているのをみかけますが、 メモリーを確保していなくても問題ないのでしょうか? char* p; p = (char*)malloc(7); strcpy(p,"abcdef"); としたのと同じでしょうか?

  • C言語の領域確保について

    C言語を始めたばかりのものです。 配列を計算させようと下のようなプログラムを作り、一応動作はするのですが、配列の領域確保がいまいちわかりません。配列はcsvから値をとっています。確保する領域は、代入する値の数でいいので、buff[8×64]、とかarv[4×32]でいいと思い、それより少し大きな値くらいで実行すると失敗してしまいます。  自分の理解の仕方が間違っているとは思っているのですが、(char *)malloc(M*N*sizeof(char))でやっても失敗しました。どうすればよいかお教え願います。ちなみに、csvの値は0.000852354710804709のように桁が半端ないです。  またfgetsのライン数の値も正しくするにはどうすればよいのでしょうか。できたらmallocを使えたらよいと思っています。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #define N 8 //8行 #define M 64 //64列 int main() { char *fname = "test.csv";//8行64列 char *ffname = "tk.csv";//4行32列 FILE *IN1, *IN2, *OUT1, *OUT2; char buff[100000];//←問題の部分 char *pbuff; char arv[400];//←問題の部分 char *parv; double a[N][M+30], b[N][M], c[N][M], w[4][32]; int i, j, x; double m, n; int count=0; if((IN1 = fopen(fname, "r")) == NULL){ printf("can't open the %s", fname); return 0; } if((IN2 = fopen(ffname, "r")) == NULL){ printf("can't open the %s", ffname); return 0; } i=j=0;//配列の取得 while(fgets(buff, 100000, IN1) != NULL){ pbuff = buff; while((pbuff = strtok(pbuff, ",\n")) != NULL){ a[i][j++] = strtod(pbuff, NULL); pbuff = NULL; } i++; j=0; } i=j=0;//配列の取得 while(fgets(arv, 400, IN2) != NULL){ parv = arv; while((parv = strtok(parv, ",\n")) != NULL){ w[i][j++] = strtod(parv, NULL); parv = NULL; } i++; j=0; }             :             :             : このプログラムでも計算はできるのでいいのですが、最終的には500行2048列の計算をしないといけないので、いっそう数字が膨大となるために質問させていただきました。Visual Stdio 2010 c/c++ 使ってます。

  • 動的なメモリ領域の確保

    double型変数5個分のメモリをmalloc関数により確保し,その確保した要素のアドレスを表示するように,プログラムを作る問題で、 (注)に「 %pで表示するためには,double型へのポインタ(double *)をvoid型へのポインタ(void *)にキャストする必要がある.」と書かれていたのですが、どういうことでしょうか? 以下のようでいいのでしょうか? #include<stdio.h> #include<stdlib.h> #define COUNT 5           // 動的に確保するメモリ領域数を示すマクロ定数の定義 int main(void) {  // 動的に確保するメモリ領域のアドレスを保持するポインタ変数の宣言  double * pointer;  int i;                  // for文で使用する変数の宣言  // int型変数5個分のメモリ領域を確保  pointer = (double *)malloc(sizeof(double) * COUNT);  if(pointer == NULL) {        // メモリ領域の確保が失敗した場合   printf("メモリ領域を確保できませんでした.\n");   exit(1);                // プログラムの終了  }  for(i = 0; i < COUNT; i++)   printf("%d番目のアドレスは%pです.\n", i + 1, pointer + i);  free(pointer);            // 確保したメモリ領域の解放  return 0; }

  • mallocとfree

    struct list *p; /* 記憶領域の確保 */ if ((p = (struct list *) malloc(sizeof(struct list))) == NULL) { printf("malloc error\n"); exit(1); } とサンプルプログラムがあるのですが、if分の意味がわかりません。 また、mallocを使った場合freeで開放とあるのですが、 どういう意味なのかわかりません。 よろしければ、上記2つの点について教えてください。

このQ&Aのポイント
  • ステンレス配管のねじ切りにはどれくらいの厚さが必要なのか気になります。今回、50Aの配管を10Aや20Aに変更する予定ですが、Sch20Sの厚さでねじ切りできるのか心配です。実務的にどのくらいの厚さが必要なのでしょうか?
  • ステンレスの配管をねじ切りする際には、接合部の厚さに注意が必要です。今回は50Aの配管を細い配管に変更する予定で、Sch20Sの厚さを使用する予定です。しかし、ねじ切りに必要な厚さはどのくらいなのでしょうか?実務的には40Sぐらいの厚さが必要なのか気になります。
  • ステンレス配管のねじ切りにはどれくらいの厚さが必要なのか悩んでいます。今回、既存の50Aの配管を10Aや20Aに変更する予定ですが、Sch20Sの厚さでねじ切りしても問題ないでしょうか?実務的にどのくらいの厚さが必要なのか知りたいです。
回答を見る

専門家に質問してみよう