• ベストアンサー

メモリとポインタと配列と

malloc()を使用して可変の変数を作り加工。 後々に参照するためにポインタの配列に格納したいと考えております。 malloc()を行った後は必ずfree()にてメモリを開放せねばなりませんが、開放するとポインタの配列に格納した値も消えてしまいます。 だからといって開放せずにいるとメモリリークが起きてしまいます。 この様な場合はどのようにすればよろしいのでしょうか? 大体以下のような処理を考えております。 ご教授願えれば幸いです。 ****************************************   char *p[100];   for(int i=0;i<100;i++) {     char *word1 = "あいう";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     int size = strlen(word1) + 1;     char *memo1 = (char *)malloc(size);     if (memo1 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     strcpy(memo1, word1);          //・     //・ *memo1 を利用した処理。     //・     char *word2 = "abc";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     size = strlen(word1) + 1 + strlen(word2) +1;     char *memo2 = (char *)malloc(size);     if (memo2 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     memset(memo2, 0x00, size); //初期化     strcpy(memo2, word2);     strcat(memo2, "\t");     strcat(memo2, memo1);     p[i] = NULL;     p[i] = memo2;     free(memo2);     free(memo1);   } **************************************** 宜しくお願いします。

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

  • ベストアンサー
  • Yanch
  • ベストアンサー率50% (114/225)
回答No.1

●ポイント1 C++を使っているなら、malloc() & free()よりもnew & deleteの方が良いんじゃないかな。 ●ポイント2 処理の流れが整理されてないように思います。 ----------------------------------------------------------------------   char *p[100];   // ●配列pを初期化。   for (int i = 0; i < 100; i++) {     p[i] = 0;   }      // ●memo1を利用した処理?。   for (int i = 0; i < 100; i++) {     char *word1 = "あいう";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     int size = strlen(word1) + 1;     // char *memo1 = (char *)malloc(size);     char *memo1 = new char[size];     if (memo1 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     strcpy(memo1, word1);          //・     //・ *memo1 を利用した処理。     //・          char *word2 = "abc";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     size = strlen(word1) + 1 + strlen(word2) +1;     char *memo2 = (char *)malloc(size);     if (memo2 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     memset(memo2, 0x00, size); //初期化     strcpy(memo2, word2);     strcat(memo2, "\t");     strcat(memo2, memo1);          p[i] = memo2;     // free(memo1);     delete [] memo1;   }      // ●メモリ解放処理   for (int i = 0; i < 100; i++) {     // free(p[i]);     delete [] p[i];     p[i] = 0;   } ---------------------------------------------------------------------- やりたい処理はこんな感じかな。

mikami532
質問者

お礼

ありがとうございます! まさにやりたかったことです。 環境的にはC++なのですが、全体的にCで書かれている為、上記をCに置換して試してみます。 forの外で配列分確保する。。。ここに気付けませんでした。 また memo1 を開放するのではなく、p を開放する。 これは勉強になりました。

その他の回答 (2)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.3

プログラムの仕様上、動的に確保した領域を二度と使わないと わかった時点で開放する。 それだけ。

mikami532
質問者

お礼

回答ありがとうございます! 確保と開放のタイミングが掴めず悩んでおりました。 もっと学習いたします。

回答No.2

  >p[i] = memo2; >free(memo2);  この、"free(memo2)"は、"free(p[i])"と同じだということは、 判っているのでしょうか。  

mikami532
質問者

お礼

回答ありがとうございます! free(memo2) をしなければメモリーリーク。 free(memo2) をすればp[i] も消えてしまうため、悩んでおりました。

関連する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 が代入された 時点でしょうか? どうぞよろしくお願いいたします。

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

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #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));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • ポインタについて

    C言語では char *p; と宣言しておいてそのポインタに p = "ABC"; というように指定できると思います。 参考URL http://www9.plala.or.jp/sgwr-t/c/sec10-3.html このようにしてポインタを使用した場合、freeで開放する必要はあるのでしょうか。 配列で文字列を指定した場合 char str[] = "ABC"; スタック領域に確保されるので、宣言したメソッドが終わった場合、自動的に開放されると思いますが、malloc等でヒープ領域にメモリを確保した場合、freeで開放されるまではメモリ上に残っていると思います。 動きを見てみると、 char *p; p = "ABC"; もメソッドが終わってもメモリ上に残っているように思えるのですが、 開放する必要があるのでしょうか。 上記のような指定の仕方は使わなければいいだけなのですが、 気になってしまいました。 変な質問ですいませんが、宜しくお願いします。

  • ポインタと配列

    次のソースで、結果表示でポインタを使いたいのですが、うまくいきません。1件しか表示されないのです。 ポインタの扱いがおかしいのだと思いますが、どうしたらよいでしょうか? #include <stdio.h> #include <string.h> int search(char key[256],FILE *fp,char *result[256][256]); main(void) { FILE *fp; int rep,n,i; char x[256],key[256],*result[256][256]; printf("検索キーワードを入力してください。\n" "キーワード>"); gets(key); if((fp=fopen("personal.txt","r"))==NULL) { printf("ファイルをオープンできません\n"); exit(1); } printf("=====検索結果=====\n"); n=search(key,fp,result); for(i=0;i<n;i++) { printf("%s\n",result[i]); } printf("検索結果:%d件です。\n",n); fclose(fp); } int search(char key[256],FILE *fp,char *result[256][256]) { int n=0; char *p,word[256],*name; while((p=fgets(word,256,fp))!=NULL) { if(strstr(word,key)!=NULL) { name=strtok(p," "); strcpy(result[n],name); n++; } } return n; } 実行すると、下の警告がでます。 illegal pointer combination(param)

  • メモリの解放について

    文字列の左右のスペースを削除する関数を作っています。 そこで引数の文字列と同じ領域のメモリを確保し、そこで一時的にスペースを削除する作業をしています。 作業が終わったら、引数のポインタに文字列をコピーし、作業領域を解放したいと思っています。 しかし、確保した領域を解放しようとすると、「セグメンテーション違反」なるエラーが出て、解放できません。どなたか分かる方ご教授お願いします。 void trim(char *str) { int i; int len; char *tmp_p, *save_p; tmp_p = (char *)malloc(strlen(str) + 1); strcpy(tmp_p, str); save_p = tmp_p; len = strlen(tmp_p); // 後方スペース削除 // ポインタを最後まで進める for(i = 0; i < len - 1; i++) { tmp_p++; } // 文字だった場合'\0'でターミネート while(tmp_p != save_p) { if(!isspace(*tmp_p)) { tmp_p++; *tmp_p = '\0'; break; } tmp_p--; } // 前方スペース削除 // ポインタを最初に戻す tmp_p = save_p; // 文字が出てくるまでポインタを進める while(isspace(*tmp_p)) tmp_p++; strcpy(str, tmp_p); // free(tmp_p); // <- セグメンテーション違反 }

  • メモリ

    メモリについてご質問します。 例えば 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回ごとに新たなメモリをとっているのか 更新されていっているのかがわかりません。

  • c言語のポインタ

    学校で、名前、住所などを構造体に入力するというプログラムをc言語で書いています。 そこで、質問なんですが・・・ fgetsで文字を入力し、構造体にデータを入れる関数に渡すと セグメンテーションエラーになってしまいます。 文字列のポインタの問題だと思うのですが、よくわかりません。 誰か教えてください!! ーーーーソースーーーーー printf("name "); fgets(xx,255,stdin); printf("%s",xx); printf("tel "); scanf("%s",t); strcat(t,"\n"); printf("zip "); scanf("%s",z); strcat(z,"\n"); printf("add "); scanf("%s",ad); strcat(ad,"\n"); printf("email "); scanf("%s",em); strcat(em,"\n"); root = makenode( *xx,ss,y,t,z,ad,em, root ); //関数で構造体にデータを挿入する 関数 BinNode *makenode( char *x,char *t,char *z,char*ad,char *em, BinNode *current ) { if( current == NULL ) //currentに何も入っていないとき { current = (BinNode*)malloc(sizeof(BinNode)); //領域を確保する strcpy( current->data, x ); //読みを入力 strcpy( current->tel, t ); //電話番号を入力 strcpy( current->zip, z ); //郵便番号を入力 strcpy( current->add, ad ); //住所を入力 strcpy( current->email, em ); //emailを入力 current->left = current->right = NULL; //右と左のノードをNULLにする }

  • get()を否定されました…どのように直せばいいでしょうか…

    プログラムで、文中のpikatyuという文字をraityuに変換させるプログラムを作れという問題で、以下のプログラムを作成しました。 すると、警告文で prog.c: In function 'main': prog.c:14: warning: unused variable 'c' prog.c:33: warning: control reaches end of non-void function /var/tmp//cc1HByZn.o(.text+0x51):Infunction 'main': : warning: warning: this program uses gets(), which is unsafe. というものが出てきました。 コンパイルはできるのですが、 講師がgets()を使うなと言うのです。 どのようにすれば認めてもらえるのでしょうか? どこをどのように直せばいいか教えてください。お願いします。 #include<stdio.h> #include<string.h> #define SIZE 512 char *search(char *,char *); void replacce(char *,char *,char *); int main(int argc,char, **argv) { char c; int i = 0, j = 0; char a[SIZE][SIZE]; for (i = 0; i < SIZE; i++) { gets(a[i]); } while(a[j][0] != '\0') { replace(a[j],"pikatyu","raityu"); printf("%s\n", a[j]); j++; } } void replace(char *text, char *key, char *rep) { char *p,buf[SIZE]; p = search(text, key); while(p != NULL) { *p ='\0'; strcpy(buf, p + strlen(key)); strcat(text, rep); strcat(text, buf); p = search (p + strlen(rep), key); } } char *search(char *text, char *key) { int m, n; char *p; m = strlen(text); n = strlen(key); for(p = text; p <= text + m - n; p++) { if(strncmp(p, key, n) == 0) return (p); } return (NULL); }

  • プログラミング(配列と関数の引数)

    a : ABCDE a : ABCDEFGH Len : 8 a : FGHIJ a : FGH a : FGH, c : FGH 上記のように表示されるプログラムを作りたいのですが、なかなかできません。下記のようなプログラムを作ったのですがどこが間違っているのかよくわかりません。分かる方、指摘をお願いします。 #include <stdio.h> void my_strcpy(char s[], char t[]); int my_strlen(char s[]); void my_strcat(char s[], char t[]); int main(){ char a[10]; char b[10] = "ABCDE"; char c[] = "FGH"; int len; my_strcpy(a, b); printf("a : %s\n", a); my_strcat(a, c); printf("a : %s\n", a); len = my_strlen(a); printf("Len : %d\n", len); my_strcpy(a, "FGHIJ"); printf("a : %s\n", a); a[3] = '\0'; printf("a : %s\n", a); if(strcmp(a, c) == 0){ printf("a : %s, c : %s\n", a, c); } int i, s, t; my_strcpy(a, b + 2); printf("a : %s\n", a); void my_strcpy(char s[], char t[]){ for (i = 0; t[i] != '\0'; i++){ s[i] = t[i]; } s[i] = '\0'; } int my_strlen(char s[]){ int i; for (i = 0; s[i] != '\0'; i++); return i; } void my_strcat(char s[], char t[]){ int i, j; for (i = 0; s[i] != '\0'; i++); for (j = 0; t[j] != '\0'; i++, j++){ s[i] = t[j]; } s[i] = '\0'; } }

  • reallocの断片化対策について

    初めにお断りしておきたい事があります。 出先で緊急な事でしたので、今即興で書いたソースになります。 Cコンパイル環境が有りませんでしたので、動作確認がとれておりません。 その為、ケアレスミス等有るかもしれませんがご容赦願います。 例として標準入力より文字列を取得する処理を記述しました。 以下の処理でreallocの際の断片化対策となるでしょうか。 (最終的に*strにセットされている領域が断片化されていない事) 実際の処理では1行辺り0~30000文字程の可変長の文字列を読み込む事を想定しております。 C(windows)のみ可でC++は不可になります。 その他、冗長な記述等指摘が有りましたらよろしくお願い致します。 #define MAX_BUF_SIZE 128 int getText(char **str) { char *buf[MAX_BUF_SIZE]; char *tmp = NULL; int tmpsize = 0; if ((tmp = (char*) malloc(1)) == NULL) { return FALSE; } *tmp = '\0'; while (fgets(buf, MAX_BUF_SIZE, stdin) != NULL) { tmpsize += MAX_BUF_SIZE; if ((tmp = realloc(tmp, tmpsize)) == NULL) { free(tmp); return FALSE; } strcat(tmp, buf); } if (*str != NULL) { free(*str); } if (*str = (char*) malloc(strlen(tmp) + 1) != NULL) { return FALSE; } strcpy(*str, tmp); free(tmp); return TRUE; }