• ベストアンサー

メモリの確保について教えてください。

いつも拝見させて頂き、かなり勉強させていただいております。 今日は思い切って質問させていただきます! まだ独学でC言語の勉強を始めたばかりなので、分かっていないことも多く、不明瞭な書き方になってしまったら、申し訳ありません。 ファイルやデータベースから情報を読み込み、それを別のデータベースへインサートするプログラムを作っています。 fgetsやfetchでデータを取得するのですが、これまではループ(while(1))を使って 1行分のデータを取得し、簡単な処理(printfやカウントを取る等)をして、別データベースへインサートする。 という処理を、全てループ内で行ってきました。 しかし、今回は構造体を用意し、データの件数分の構造体領域をmallocで確保して簡単な処理を行い、別データベースへインサートするという課題があります。 mallocでは必用な分だけメモリを確保できるため、無駄がないと知りましたが、前に書いたようにループ内で取得からインサートまでを行う処理でも無駄は出ないように思います。 だとしたら、ループ内で全ての処理を行うのと、メモリを確保するのとでは何か違いや利点があるのでしょうか? もしくは、方法の違いだけで、どちらを使うかは違いがないのでしょうか? とても基本的な質問でしたら、申し訳ないのですが アドバイスを頂きたいと思います。どうぞよろしくお願いいたします。

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★単純に入力から出力へデータを送るなら malloc は不利。 ・メモリを確保するのにも『多少』時間がかかりますし、もし万が一メモリ不足になったらその場合の  処理・対策をループ内などで行う分面倒です。 ・他にもデータベースを読み取り、別のデータベースへインサートするだけならばループ内で行う方が、  1行分のデータメモリで済みます。メモリ資産を大切に! ・それで、今回は『構造体』にデータ件数を読み込んで『簡単な処理』を行った後、別のデータベースへ  インサートする課題ですね。 ・読み込んだデータでどんな処理を行うか分かりませんが、ソートなどを行うには一括で構造体などに  読み込んでから処理した方が効率が良いでしょう。このように『一括』で処理するにはメモリへ読み込む  必要がありそうです。これ以外は特に malloc 関数を使って処理する意味はないように思います。 ・もし、単純なカウントだけならば『課題』という『malloc』関数の勉強という意味ぐらいでしょね。  多分、『構造体』と『malloc』関数の使い方のための『課題』でしょう。 ・以上。おわり。→参考にして下さい。

empuru
質問者

お礼

Oh-Orange様 丁寧なご回答をどうもありがとうございます! とても勉強になりました。 データを一括して処理をするため、構造体へ読み込む必用があるということに気づいていませんでした。 今回の課題では一括して処理をするようなことはないようにも見えるのですが、私が気づいていないだけかも知れません。 本当にありがとうございました。

その他の回答 (3)

  • amru05
  • ベストアンサー率63% (33/52)
回答No.4

現実の場合、 1)I/O処理は時間がかかるので、なるべく少ない回数が良い   たとえば、ループで100回I/Oするより、100回分のデータエリアを確保しておき、1回のI/Oで済ませる方が早い。 2)データエリアの確保方法として変数をアレーにし関数内に記述するのが簡単だが、そうするとスタック上にデータエリアが確保されてしまい、処理系にも寄りますが、大体8M程度のデータサイズまでしか確保できない(コンパイラの設定で増加できますが、VC++などはデフォルトが大体8Mだったような。。。)。 3)関数外にグローバルに変数をアレーにし確保する方法もあるが、これも限界がある(VC++で256M程度だったような。。)。 4)それ以上に大きなエリアを確保するにはmallocを使用する(32ビットOSの場合2G程度までは可能のはず。。) 5)それでも不足する場合64ビットOSでmallocを使用する。   ==> まあ、こんなものです。私は5)まで必要なAPLを作成していますが、通常は滅多に無いので3)程度で終わらせています。   ある程度のエリア確保とループ処理の組み合わせが現実的だと思います。

noname#39970
noname#39970
回答No.2

ループ内で終わっているなら手間の分だけmallocの方が手間。 No1でも書かれてるけど、そうでなくループ外や ループのように見える場合や処理を別の場所に渡す場合などの改造を施す場合はどうするつもり? メモリ確保が要るんじゃない?

empuru
質問者

お礼

SAYAKA様 ご回答ありがとうございます。 一括しての処理の他に、処理を分けたりする際に必要ということに気が付きました! 改造まで考えていなかったので、新たに気づくことができました。 ありがとうございました。

  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.1

処理としては意味はないが、課題として意味があるというだけかもしれません。 ひとつの入力レコードに施す加工がそのレコードに閉じているのなら、1レコード分だけのメモリをmallocすれば足ります。

empuru
質問者

お礼

a-saitoh様 ご回答ありがとうございます。 1レコード分すらmallocしていなかったため、ループ内で行う際もmallocするということに気が付きました。 どうもありがとうございました。

関連するQ&A

  • 動的なメモリ確保の仕方

    ユーザーが入力した任意個数のデータを受け取り、 それらの平均、標準偏差などを求めるプログラムを 書いてみようとしています。 この「任意個数」については、メモリを確保できる限りの 限界個数まで入力可能にしたいと考えています。 今時のメモリー容量なPCでそんな個数のデータを 入力することがあるかどうかはとりあえずおいておきます。 これまで、方法として以下2つを検討しました。 ■あらかじめ限界サイズの配列を用意する。  ※int型配列なら、int matrix[0x7FFFFFFF/sizeof(int)]など。 ■「n個目の入力値用変数」と、   「n+1個目の入力値用変数のアドレスを格納するポインター」の  構造体を用意して、入力個数が一つ増えるたびにmalloc()でデータ領域を確保していく。 ただ、前者は必要ない時でも大容量のメモリを食う巨大な無駄がありますし、 後者は、次データの位置を示すポインタ情報の付加分だけメモリ使用効率がおちます。 そのため、どちらもいまいちな気がしています。 世の中には、こんな方法よりずっと効率的なデータの確保方法があるに違いないと 思っているのですが、なかなかそれという情報にネットで出会えていない状態です。 何か良い方法をご存じの方、ご教授願えないでしょうか?

  • アドレス格納のための二次元配列のメモリ動的確保

    アドレス格納のための二次元配列のメモリ動的確保 二次元配列のためにメモリを動的確保しなければならないのですが、 その配列に格納したいものが 「DATA型のポインタ」です。(DATA型はtypedefした構造体です。) プログラム実行中にmallocで確保した、数あるDATA型の構造体の、その先頭アドレスを リストアップするための配列です。 この場合、どのような形でmallocすればよいのでしょうか? 教えていただけるとありがたいです。よろしくお願いいたします。 -- たとえば m×n のint型の配列は、 ◆ int *i; ◆ i = (int *)malloc( m * n * sizeof(int) ); となりますよね。 この要領がでやるのが一般的にわかりやすいものだとするならその方法でやりたい (後発の人が自分のソースコードを読む可能性があるため)のです。 -- 同様にm×nの「DATA型のポインタを格納するための二次元配列」を動的確保したい場合、 ◆ DATA *d; ◆ d = (DATA *)malloc( m * n * sizeof(DATA) ); この文にどのように付け加えたら良いのでしょう? もうあと一歩な気がするのですが(笑)。しかし参考書等で勉強しましたがわかりませんでした・・・。 わかる方、どなたかよろしくお願いいたしますm(_ _)m あとこれだけ通ればコンパイルが通るんです!!!!! たぶん(笑)

  • 構造体のメンバのメモリ確保について

    構造体の中の一部のメンバだけをmalloc関数で メモリ確保したいのですがどのように宣言すればよいのでしょうか? vc++6.0を使用しています。 初歩的な質問ですみませんがお願いします。

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

    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); 大変申し訳御座いませんが、 ご指摘・ご指導願いませんでしょうか? どうか宜しくお願い致します。

  • メモリ動的確保について

    こんにちはです。 メモリの動的確保なのですが、 typedef struct DATA{ char name[256]; char pass[256]; int money; }BANK; void insert(BANK *p,int max); int main(){ int i; size_t st; BANK *person; person = (struct DATA *)malloc(sizeof(struct DATA)); //person = (struct DATA *)malloc(5); if(person == NULL){ printf("確保失敗\n"); exit(-1); } //memset(person,'\0',sizeof(struct DATA)); と、言う風に、記載ソースは途中ですがメモリをとりました。 mallocの後ろの部分ですが、sizeof(struct DATA)と5ではどうちがうのでしょう??2通りともコンパイルエラーはないです。 5は動的に最大5までとるって事はわかるのですが、struct DATAの方はいくつとるのです??いくつもで入力次第です? そして、動的したのにたいしてmemsetしたら実行エラー(コンパイルは通りました)おきました。動的にたいしてmemはダメなのでしょうか? アドバイスいただけたらありがたいです。宜しくお願いいたします。

  • mallocによる確保外の領域への参照

    構造体をmallocにより動的確保を行っていたのですが、例えば typedef struct _point{ int x, y; } point; point *pelem_point; pelem_point = (point *)malloc(sizeof(point)*5); このように、point型の構造体を5つ確保するとします。 しかし、 (pelem_point+100)->x = 1; (pelem_point+100)->y = 2; printf("%d\n", (pelem_point+100)->x); printf("%d\n", (pelem_point+100)->y); とやったら、確保していない100個先のところも構造体として利用できました。 なぜなのでしょうか。 自分の考えではこのようになりました。 mallocによりヒープ領域から適当な空いているメモリのアドレスが渡されるため、そこからはヒープ領域より先に、限りがあるまで進めてしまうために確保外のサイズにアクセスしても使えてしまっている。 また、mallocにより確保した場合は使用中のラベルがはられるため他に侵されることはないが、先の例のようにmallocによって確保してない場合はいくら使用できたとしても、空いているとコンピュータでは認識されるため、何かヒープ領域を使う場合に勝手に上書きされてしまう可能性がある。 しかし、この考えでも、なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。 わかる方いましたらよろしくお願いします。

  • 構造体のメモリ確保のキャストについて

    構造体のメモリ確保をする際に、処理系はVC++ 6.0なので キャストしなければならないのですがどうすればよいか分かりません。 構造体にはint型とchar型が入っているのですがこの場合はどのようにキャストすればよいのでしょうか? お願いします。

  • C言語のメモリ領域確保

    ポインタ変数ををmain関数で宣言し、関数test()にて必要分だけ領域確保してそのアドレスをmain関数のポインタ変数に渡して利用することは可能でしょうか。 (サイズのわからないテキストデータを、十分に大きな配列に入れるのではなく、関数でメモリを動的確保して無駄の無い配列に入れたい等) C言語ではやはり無理で、構造体のリストにするのが一番でしょうか。 初歩的なことで申し訳ありませんがどなたかお願いいたします。

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

    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)が増えてしまうので,何か良い方法(コードが短くなるような)はないでしょうか?

  • malloc関数によるメモリの確保

    C初心者です。 malloc関数によるメモリの確保に関して教えてください。 2次元配列のサイズに対してmalloc関数の引数値をたとえば、 (double*)malloc(datasize*sizeof(double)) などとしメモリ領域を確保すると、メモリアドレスはデータのサイズ によらず一定 1234044、1234048となります。 データサイズを大きくし、datasize*sizeof(double)が16Kバイトを超えるとcmd.exeがエラーとなり落ちます。 デバックモードで実行すると 「"System.AccessViolationException"のハンドルされていない例外が不明なモジュールです。で発生しました。 追加情報:保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリがこわれていることが考えられます」 というメッセージがでます。 コンパイラはExpressEdition2008です。 この現象を回避するにはどうすべきか、なぜこのようなことが起こるのかご教授ください。 よろしくお願いいたします。