• ベストアンサー

メモリーの確保について

皆さんはプログラムをするときに入力に応じて配列の大きさが変わるような場合には下記の方法のどれでプログラムしますか?こうすべきなのがベストだ!みないなお考えを聞かせてください。 (1)char str[100]のように大きなサイズを前もって用意しておく。これだとあとからデバック時に100って何か意味があるのかとか悩んでしまったりすると思います。 (2)malloc()とfree()関数を使って動的にメモリーを確保する (3)ポインタ配列を使う。char *strとか。 (4)その他 ご教授をよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.3

用途によります。 例えばエディトボックス等で入力が100文字が上限なら char str[101]で事足ります。しかしその辺はどんぶり勘定で 128とかで良いかと思います。 スペックにもよりますが今のPCだと27バイトの隙間なんて どうでも良い話です。 malloc,freeが良いかというと、それは環境によります。 malloc,freeを繰り返すとメモリが断片化するので メモリの少ないコンシュマーゲームの開発などではあまり使いません。 ポインタ配列も同じです。 VC++ならCStringクラス、STL(C++)ならstringやwide文字に対応した wstringといったテンプレートが用意されています。

20centuryboy
質問者

お礼

回答ありがとうございます。 malloc,freeを繰り返すとメモリが断片化するのは知りませんでした。ゲーム開発ではあまり使わないとは非常に貴重な情報ありがとうございます。c++はわからないのですが、Cが使いこなせるようになったらチャレンジしてみようと思います。どうもありがとうございました。

その他の回答 (4)

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

既に回答にあるようにケースバイケースですから、ベストの方法は無いと言えます。 データの内容,処理速度,メモリ容量,作成にどれぐらい手間をかけるか,データサイズ、スタックサイズ、使われる場所(?)等で変えます。 勿論,(1)のケースでは#defineなりconstなり使いますが。 後は,内容によってはデータ構造として配列以外を使うこともあります。 リスト、スタック、リングバッファ・・・。

20centuryboy
質問者

お礼

回答ありがとうございました。 やはり状況によって使い分けるのですね。 メモリマップの話はあまり理解していないのですが、今度じっくり勉強してみようと思います。 ちなみに私はC言語のスキルはひよっこレベルなのでまだまだ皆さんに比べるとわからないことが多いのですが、constは実引数を変更したくない時に使うものだと思っていたのですが、それ以外に使い道があるということですか?調べてみようと思います。リストやスタックなども使えるように勉強していきたいと思います。 どうもありがとうございました。

  • sisya
  • ベストアンサー率39% (97/245)
回答No.4

ゲームなどのメモリを確保する時間もなるべく短縮したい場合は、 その変数に使用するであろう最大のサイズを「define」で宣言し、 宣言時に数字直打ちにならないようにしています。 ex) cher srt[MAX_LENGTH]; 確保に要する時間は気にしないと言う場合は、 (2)の手段で領域を確保します。

20centuryboy
質問者

お礼

回答ありがとうございます。 メモリーの確保時間が(1)の方が早いとはためになりました。 何を開発するかをひっくるめて状況によるのですね。 どうも貴重な情報をありがとうございました。

  • gentaro
  • ベストアンサー率47% (105/221)
回答No.2

最近はPHPばかりでメモリ領域確保なんてとんと忘れていました(笑)。 私の場合、1次元配列ただ1個なら(1)が多いですね。#1の方と同じようにソースの頭やヘッダで定義しますけど。 多次元配列や構造体配列なんかのときで数が不定なら迷わず(2)です。(3)にしても実エリアは領域確保しなきゃなりませんし。

20centuryboy
質問者

お礼

回答ありがとうございます。 phpはほんのちょっとだけかじったことがあるのですが、メモリ確保がいらないとは初耳でした。多次元もしくは構造体配列のときならmallocなどを使うですか...参考になります。 どうもありがとうございました。

  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.1

 Cで作成するときには、2と3ですね。この二つ、本質的には、同じかな・・・malloc freeで動的メモリーを確保し、それをポインターを経由して利用する。(目的に応じては、char **str とポインターの配列になるときもありますが・・・)  ただ、小さい関数で、最大のデータサイズが何らかの方法で確定できるときは、1の方法も使います。入力関数のデータバッファ等ですね。  この手を使う場合は、#define MaxNanchara 100のように記号化した上で、何チャラの部分に大きさを確定した理由を推測できる言葉を選んでます。  この場合も、処理後には、結局動的メモリーにうつすことになりますけど。  ちなみに、C++でしたら、メモリー管理をさぼるために、stringクラスや、vectorクラスで対応することが圧倒的に多いです。なにせ、これが一番楽ですから(苦笑)

20centuryboy
質問者

お礼

回答ありがとうございます。そうですね2と3は本質的には同じでした。確定できる時には#defineで明示するのがやはり通説ですね。 C++はわからないのですが、これからCをある程度つかいこなせるようになったら勉強してみたいと思います。stringクラス、vectorクラスは覚えておこうと思います。ちなみに最近ではどの会社もオブジェクト指向言語を使うのですかね?ゲーム会社だとc++が多くて、ネットワーク系の会社だとjavaが多いとかのように私は思っているのですが。

関連するQ&A

  • 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関数等を自作とかされていますでしょうか?  どうぞよろしくお願い致します。

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • reallocでメモリを再確保するには?

    こんにちわ, 今, 「すでに動的確保しているメモリをその型分1サイズだけ増やす」というプログラムを考えています。 具体的には, char* str_p; a=calloc(str_p, sizeof(char)); /*ここから問題のプログラム(実際はずっと動くので無理です*/ while(1) { a=realloc(str_p, sizeof(str_p)+sizeof(char)); } ・・・・・・ これだと,私的にはsizeof(str_p)で今のサイズを調べ,それにsizeof(char)を加えることで次々に1サイズ大きいメモリを再確保できると思ったのですが,ポインタのサイズを指していてそれにchar型のサイズをたしていていつも固定サイズになるみたいでうまくいきません。 どうすれば,char*などポインタ型の変数の大きさを調べられるのでしょうか。 また,どうすれば,1サイズずつ大きくできるのでしょうか。 よろしくおねがいします。

  • メモリ領域確保に関して

    C言語を始めて3ヶ月の初心者です。 下記のような定義で、領域確保をしたいのですが、 うまい方法がわかりません。 ご存知の方いらっしゃいましたら、 御知恵をお貸し下さいませんでしょうか? <test.h> ================================== #define SIZE_A (5) /* 親構造体 */ typedef struct { int testInt; testSmallStructT *testSmall; // 7バイト構造体の配列 char *testChar; // SIZE_A分の領域*配列数 } testBigStructT; /* 7バイト構造体 */ typedef struct { char str1[3]; char str2[4]; } testSmallStructT; /* メンバ変数 */ testBigStructT gTest[10]; ================================== ここで、あらかじめ全体の領域サイズを算出して、 mallocにてエリア確保を行う方法を求めてます。 また、多数にmallocを使用するとメモリ確保失敗時に、 それまで確保したエリアの開放を行わなくてはいけなくなる懸念から、 できるだけ使用しないようにしたいのです。 メンバ変数gTestを10の配列で持ち、構造体testBigStructTの、 要素testSmallとtestCharを可変の配列として扱いたくポインタ定義をしており、 更に、testCharにSIZE_A(5byte)の領域を確保しようとしております。 最終的には、下記のような使い方をしたいのですが、 メモリ確保の方法がわかりません。 =================================== (EX:) strcpy(gTest[0].testSmall[0].str1,"aaa"); strcpy(gTest[3].testSmall[2].str2,"bbb"); strcpy(gTest[6].testChar[3],"cccc"); =================================== 開放は下記の記述で問題ないと思っております。 free(gTest); 大変申し訳御座いませんが、 ご指摘・ご指導願いませんでしょうか? どうか宜しくお願い致します。

  • 2次元配列の動的確保

    ある画像を読み込むため、その画像を格納できる幅、高さを持った配列を動的に確保しようと考えています。 幅をxsize、高さをysizeで次のように記述しました。 unsigned char **src; int i; src = (unsigned char**)malloc(sizeof(unsigned char*) * ysize); src[0] = (unsigned char*)malloc(sizeof(unsigned char) * xsize * ysize); for(i=1; i<ysize; i++) src[i] = (src[0] + i * xsize); わざわざポインタのポインタを使用したのは、動的に確保した配列を2次元的なアクセスをしたかったためです。 画像の読み込み時は fread(src[0], sizeof(unsigned char), xsize * ysize, fp); としています。 上に記述したソースは問題なく動作しました。 しかし、上の場合だと全ての配列を連続して確保することができません。つまりsrcでmallocを一回、src[0]でmallocを一回使っているため、ポインタの配列の直後に配列を確保する保障がありません。そこでいっぺんに確保することを考えました。 unsigned char **src; int i; src = (unsigned char **)malloc(sizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize); for(i=0; i<ysize; i++) src[i] = (unsigned char *)(src + sizeof(unsigned char *) * ysize + i * xsize); このように組み上げ、読み込み時は上のfreadと同様に記述したところエラーが出てしまいました。 やはり一行目のmallocで無理やりsizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize分確保するのは失敗だったのでしょうか?

  • メモリの再確保について

    テキストファイルを読込む関数を作成しています。 まず最初にある程度の領域をmalloc()関数で確保し、 読み込む過程で領域が不足すると再割り当てを 行うようにしたいのですが、 エラーが出力されます。 ソース(エラー処理は省略)は次の通りです。 textdata = (char *) malloc (size * sizeof (char)); for (i = 0; !feof (stream); ) { character = fgetc (stream); textdata[i] = character; i++; if ((i % size) == 0) { temp = (char *) malloc (2 * size * sizeof (char)); memcpy (temp, textdata, size * sizeof (char)); free (textdata); textdata = temp; } } 出力されるエラーは次の通りです。 *** glibc detected *** ./lsm: malloc(): memory corruption (fast): 0x09a34198 *** (省略) アボートしました どなたか解決方法を御指導願います。

  • mallocで char *型の配列を確保したい

    char *方の配列を動的確保する必要が出たのですが、 char **array=(char **)malloc((char *) * 10); としてうまくいきません どうすれば確保できるのでしょうか 知っている方がいましたら教えてください ちなみに確保した配列はこの様に使えるようにしたいです strcpy(array[0],"testest");

  • 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のデバッグテストで※のところエラーになります。なぜなのでしょうか?

  • 関数にポインタを渡して動的確保する時について

    どうにも動的確保について間違っている気がするのでお尋ねいたします。 よくメモリを動的に確保する場合に私は次のようなプログラムを書きます ポインタを用意する(例えばint *p) mallocでメモリ確保 ポインタを関数に渡す(Func(p)) 関数側でreallocし、値を代入する(p=(int *)realloc(p,sizeof(int)*num)) 関数呼び出し側で、その値を使う しかし、この方法を使うとどうにも関数を呼び出した際のポインタ(p)と、reallocした後のポインタ(p)の値が違うことがあり、値が不定になることがあります。 (reallocのメモリの確保の仕方のせいでしょうか) この使い方は恐らくどこか間違っていると思うんですが、いまいち納得のいく解決策が思いつきません。 例えばポインタを引数ではなく戻り値として得ればできますが、2つ以上のポインタについてはできません。 何卒ご教授のほどをよろしくお願いいたします。

  • 領域の確保について

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

専門家に質問してみよう