動的メモリ解放の問題とメモリ不足の原因

このQ&Aのポイント
  • 動的メモリを解放する際に効果がないため、メモリ容量が徐々に増加し、エラーが発生しています。
  • ファイルを一行ずつ読み込んでデータを取得する際に、メモリを動的に確保していますが、解放する際に問題が生じています。
  • 解放処理が正しく行われておらず、ループが進むごとにメモリ使用量が増加しています。
回答を見る
  • ベストアンサー

動的メモリ 解放がうまくいかない

よろしくお願いします。 一ファイル20万行程度のCSV形式のテキストファイルが、50個ほどあります。 これを一行づつ読み込んで、strtok( ,",")でデータを取得しようと思っています。 ファイルの行数はまちまちなので、新しいファイルを読み込むときに そのファイルの行数を調べて(ここでは count 行あります) callocをつかって、メモリを確保しました。 btxt=(char **)calloc(count,sizeof(char *));/*動的メモリ確保*/ for(i=0;i<count;i++) btxt[i]=(char *)calloc(120,sizeof(char)); /*一行120文字まで*/ if(btxt==NULL){printf("btxt 確保エラー\n"); exit(0);} 上記btxt配列にすべての行数を読み込んで、strtok()処理をした後 for(v=0;v<120;v++){ if(btxt[v]){ free(btxt[v]); btxt[v]=NULL; }  } free(btxt);  btxt=NULL; で解放してから、次のファイルに移ります。 問題は、ループするごとにメモリ容量がどんどん減ってきて、30ループもさせると メモリ不足でエラーが出ることです。 ブレークポイントを使って調べてみたのですが ループ一回目 calloc前 707.7 MB: calloc後 748.6MB 解放(したつもり)後 747.9 MB ループ二回目 calloc前 750.6 MB: calloc後 794.6MB 解放(したつもり)後 793.8 MB ・・・・・・・・・・・・・・・・・・・ ループ四回終了時には868.3MBにもなって、初めより160MBも使ってしまいます。 free()が効いてないと思うのですが、どこがおかしいのか教えてくださいませ。

  • et726
  • お礼率85% (17/20)

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

  • ベストアンサー
  • hitomura
  • ベストアンサー率48% (325/664)
回答No.2

for(i=0;i<count;i++) btxt[i]=(char *)calloc(120,sizeof(char)); /*一行120文字まで*/ for(v=0;v<120;v++) if(btxt[v]){free(btxt[v]);btxt[v]=NULL;} 上の2行をよく見比べてください。何回callocして何回freeしてますか?

et726
質問者

お礼

だぁ~ お恥ずかしい。 何回callocして何回freeしているか。肝に銘じます。

その他の回答 (1)

回答No.1

for(v=0;v<120;v++){ を for(v=0;v<count;v++){ にしないとダメなんじゃないでしょうか?

et726
質問者

お礼

ありがとうございます。 三日ほど悩んでましたw。

関連するQ&A

  • 多次元配列のメモリ解放

    多次元配列のメモリ解放についてです。 以下のような方法で多次元配列を確保した場合に、 --- char** ppMain; ppMain = new char*[3]; for (int i = 0; i < 3; i++){ ppMain[i] = new char[20]; } --- メモリ解放する場合、 --- for (int i = 0; i < 3; i++){ delete [] ppMain[i]; ppMain[i] = NULL; } delete [] ppMain; ppMain = NULL; --- で良いでしょうか? おそらく、new/deleteの回数が同じであれば問題ないと思うのですが。 少し混乱してしまって、 delete [] ppMain[i]; によって new char*[3]で確保したところも解放されており delete [] ppMain; が必要なく危険な領域まで解放しようとしているということはないでしょうか? ご専門、お詳しいかたコメント宜しくお願いします。

  • 「動的確保した2次元配列のメモリ解放」を関数化したい

    質問タイトルの通りですが、 「動的確保した2次元配列のメモリ解放」をC言語で関数化したいと思っています。しかし、関数の引数には動的確保した配列の先頭アドレスのみ渡す形にしたいです。そのような場合の関数化は可能ですか? どうもうまくいかず、困っています。 以下、具体的に、サンプルソースを記述します。 わかる方、よろしくお願いします。 //====================================================// #include<stdio.h> unsigned char** AllocByteArray2d(int column, int row); void FreeByteArray2d(unsigned char** box); int main(voidls){ unsigned char array**; array = AllocByteArray2d(2, 3); FreeByteArray2d(array); return 0; } unsigned char** AllocByteArray2d(int column, int row){ unsigned char* box; box = (unsigned char**)malloc( sizeof(unsigned char*)*column ) int i; for(i=0; i<column; i++){ box[i] = (unsigned char*)calloc( row, sizeof(unsigned char)); if(box[i] == NULL) exit(EXIT_FAILURE); } return box; } //引数では配列の先頭アドレスだけ渡す形にしたい void FreeByteArray2d(unsigned char** box){ //ここをどう書いたらいいかわからない }

  • 構造体の動的メモリについて

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUM 10 /*生徒数*/ typedef struct data { int num; /*従業員番号*/ char name[16]; /*名前*/ int jap; /*国語の点数*/ int math; /*数学の点数*/ }data; int main(void) { data test[NUM]; /*生徒のデータ*/ FILE *fp; /*ファイル操作用*/ int i; /*配列インデックス*/ int count; /*データ分割用*/ char s[100]; /*データ読み込み用*/ char *token; /*データ分割用*/ char *data[6]; /*分割データ保存用*/ fp = fopen ("data1.txt","r");        for (i=0; i<NUM; i++){ fgets (s, sizeof(s), fp); /*dataファイルから1行読み込み*/ token = strtok(s, ","); /*読み込んだデータを","で分割する*/ count=0; while (token != NULL){ data[count] = token; /*分割したデータを配列へ入れる*/ token = strtok(NULL,","); count++; } test[i].num = atoi(data[0]);       strcpy (test[i].name, data[1]); test[i].jap = atoi(data[2]); test[i].math = atoi(data[3]); } fclose(fp);       } このプログラムを構造体へのポインタの配列で管理するように変えたいのですが、どのように変更すればいいのでしょうか。 条件として、個人データを格納するメモリ領域とポインタの配列のメモリ領域は動的に確保します。 初心者でよくわからないので詳しく教えていただけると助かります。よろしくお願いします。

  • 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サイズずつ大きくできるのでしょうか。 よろしくおねがいします。

  • callocについて

    ccalloc関数を用いてメモリを確保し、15文字以下の名前をキーボードから入力を10人分繰り返し、その後にすべての名前を出力をしなさい、ただし配列は使用しないものとする。 という問題があるのですが、calloc関数を習ったことがなくうまくいかず、エラーかnullが出力されます。どなたか教えてください、お願いします。 *********ソース********* #include <stdio.h> #include <stdlib.h> void main(void) { int i; char *str; char *buf; /*メモリの確保*/ str = (char *)calloc(110, sizeof(char )); /*メモリが確保出来なかった時*/ if(str == NULL){ printf("メモリの確保ができません。"); exit(1); } /*キーボードからの入力*/ for(i = 0; i < 10 ;i++){ gets(buf); *str = *buf; str++; } /*名前の出力*/ for(i = 0; i < 10 ;i++){ printf("%s", *(str)); str++; } /* メモリの開放 */ free(str); }

  • 沢山の変数を扱う時、うまく出来ません・・。

    変数が沢山ある時、エラーが起こったかどうかは どうやって判断したらいいんでしょうか。 今50個位変数名があるとします。 今は端おって5つにします。 int a,b,d; char c,e a = (int *) calloc(500,sizeof(int)); b = (int *) calloc(200,sizeof(int)); c = (char *)calloc(700,sizeof(char)); d = (int *) calloc(400,sizeof(int)); e = (char *)calloc(100,sizeof(char)); if(a==NULL || b==NULL || c==NULL || d==NULL || e==NULL)   printf("エラー発生\n"); こうやって50個もif文の中にいれたら大変ですよね。 変数名も長いですし。うまく1つでもエラーが起きたら全体がエラーになるように出来ませんかね? 自分としてはこういう風に考えたんですけど int sum=1; a = (int *) calloc(500,sizeof(int)); sum*=a; b = (int *) calloc(200,sizeof(int)); sum*=b; c = (char *)calloc(700,sizeof(char)); sum*=c; d = (int *) calloc(400,sizeof(int)); sum*=d; e = (char *)calloc(100,sizeof(char)); sum*=e; if(sum==0)   printf("エラー発生\n"); コレくらいしかないですかね?

  • メモリの解放free()について

    メモリ解放についての質問です。 下の関数をループで呼び出すとき、new_itemのメモリ解放free()はどのように行えば良いでしょうか? typedef struct _ITEM { int n,m; void *right; } item; int data() { int i,j,k; int n,m; item *new_item,*last_item; for (i = 0; i <= M-1; i++) { ... last_item = &(list[i]); k = 0; for (j = 0; j <= num-1; j++) { /* making new item */ if ((new_item = (item*)malloc(sizeof(item))) == NULL) { fprintf(stderr,"Can't allocate memory.\n"); exit(-1); } new_item->m = i; new_item->n = k; new_item->right = NULL; last_item->right = new_item; last_item = new_item; } } }

  • 多元配列について(ANSI C)

    動的多元配列で、 Voidポインタに、多種の型がぶら下がった多元配列を作り、 読み書きをしたいのですがどのようにしたらよろしいでしょうか。 具体的には、 x[0][1]は、intで「2」が入っている x[0][4]は、intで「9」が入っている x[1][2]は、charでしかも文字列の配列で「goo」が入っている x[1][5]は、charでしかも文字列の配列で「教えて」が入っている x[0]は、int型の配列。X[1]は、文字列型の配列。 というようなものです。 一応ソースは作ってみたのですが、int型では問題なくいくのですが、 文字列は、コンパイルはできますが、実行すると予期せぬことが起きます。 #include <stdio.h> #include <stdlib.h> #include <string.h> int main (void) {      void **topPointa;      int * iDataInput;      int * iDataOutput ;      char * chDataInput;      char * chDataInput2;      char * chDataOutput1 ;      // ポインタアドレス用のメモリ確保      topPointa = (void *) calloc (10 , sizeof(void *));      if(topPointa == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      //int配列のメモリ確保      iDataInput = (int * ) calloc (10 , sizeof(int));      if(iDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      iDataInput[0] = 3 ;      iDataInput[1] = 4 ;      topPointa[0] = (void * ) &iDataInput;      //int配列の取り出し      iDataOutput = *(int *) topPointa[0];      printf( "int: %d\n", iDataOutput[0] );      printf( "int: %d\n", iDataOutput[1] );      //char配列 のメモリ確保      chDataInput = (char * ) calloc (10 , sizeof(char *));      if(chDataInput == NULL) {           printf("メモリが確保できません\n");           exit(-1);      }      chDataInput2 = (char * ) calloc (10 , sizeof(char));      if(chDataInput2 == NULL) {           printf("メモリが確保できません\n");           exit(-1);       }      strcpy(chDataInput2 , "hoe");      chDataInput[0] = &chDataInput2;      topPointa[1] = (void * ) &chDataInput;      //char配列の取り出し      chDataOutput1 = *(char *) topPointa[1];      printf( "char: %S\n", chDataOutput1[0] );      free(iDataInput);      free(chDataInput);      free(chDataInput2);      return 0; } 言語は、C言語ANCI Cでお願いします。 以上。よろしくお願いします。

  • 2次元配列を動的にメモリ確保したときの開放方法

    w = (float **)calloc(num_unit + 1,sizeof(float *)); for(i = 0; i < num_unit + 1; i++){    *(w+i) = (float *)calloc(num_unit + 1,sizeof(float)); } とメモリを取得して w[4][7]のような感じで使っているのですが、 開放するところで for(i = num_unit + 1; i > 0; i--){ free(*(w+i)); } free(w); としたらエラーが出ました。 free(w);だけにしたら一応動いたんですが、 これだけで開放できているのかメモリリークしているのか不安です。 これだと後から確保した*(w+i) = (float *)calloc(num_unit + 1,sizeof(float));の部分は 残ってしまうと思ってたんですが、どうなんでしょうか?

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

    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; }