• ベストアンサー

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

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.4

ルネサスのCコンパイラといっても、SHとH8とM16Cでは事情が違う気がしますが... ヒープ領域の使用状況をよく調べてみてください。 sbrkが呼び出されるたびに、呼出元(malloc, calloc, reallocの呼出元)を調べた方がよいでしょう。 例えば、ストリームの内部でもバッファリング用のメモリが割付けられるので、それがヒープを食いつぶしている可能性があります。 BUFSIZが512だとすれば、管理領域の4バイトを加えて、1ストリームあたり516バイト消費します。標準入力、標準出力、標準エラーの三つがスタートアップでオープンされるのであれば、516 × 3 = 1548となり、残りは500バイト。 100バイトを4回割付ければ416バイト必要なので、残りは84バイト。そして、5回目の割付けでしくじります。このとき、sbrkの定義が適切でなければ、何が起きても不思議ではありません。

youkun_1
質問者

お礼

ご回答ありがとうございます。質問に書いてあるプログラムが途中で止まる件は、解決しました。  stdlib.hをインクルードしていないという凡ミスでした。大変ご迷惑おかけいたしました。  しかしながら、本来のプログラムは相変わらず動作しません。 質問に書いたmalloc、free関数の中でループしている現象ではなく、sbrkで領域が確保できずエラーになってしまいます。  メモリーリークしているようなので、後は、回答者様のご意見を参考に、プログラムをもう一度見直してみます。  どうもありがとうございました。  

その他の回答 (3)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

「組込み系」というだけでは正確なことは何も分かりません。 処理系を具体的に補足してください。単なるコンパイラの製品名ではなく、ターゲットに合わせてmallocをカスタマイズする部分(例えばsbrkの自作など)があるはずですので、その内容についても合わせて補足してください。 なお、組込み系の多くは、「フリースタンディング環境」に分類されます。フリースタンディング環境では、規格上mallocは提供されませんので処理系の独自拡張になります。

youkun_1
質問者

補足

 ご回答ありがとうございます。コンパイラは、ルネサスのCコンパイラです。sbrkは提供されているものを使用していて、カスタイマイズしていません。またリアルタイムOSは、のせていません。  抽象的で申し訳ございませんが、質問に書いてあるプログラムくらいのものであれば、カスタマイズすることなく動作すると思っていました。  やはりスタックの問題でしょうか?  

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

if(( p1 = malloc(100)==NULL) break; のようにして,まずはプログラムミス(mallocの失敗の可能性に対応していない)なのか,他の要因なのかをまず見分けるべきでしょう. 余談ですが,mallocに(char*) はいりません. それと,メモリを2k確保と行っても,ヒープとスタックとがありますが,どっちにどれだけ割り当てているかわかりますか? 通常,mallocはヒープ(alloccaはスタック)領域が使われます.

youkun_1
質問者

補足

 ご回答ありがとうございます。メモリ2kというのは、ヒープ領域のことです。スタック領域は、700byte取って、上記プログラムを走らせました。

回答No.1

実際に見てみないので、予測の1つにしかならないですが、上記ソースを記述している関数の時点で、スタックがギリギリ、ということはないでしょうか? malloc関数はその内部でまたスタック領域を使用すると思いますが、それに耐えられないくらいの状態で、mallocが呼ばれてるとか。

youkun_1
質問者

補足

ご回答ありがとうございます。malloc関数の動作について、理解不足で、スタック領域を使用するということは考えていませんでした。  malloc関数は、どれくらいスタック領域を使用するのでしょうか? (確保する領域にもよるのでしょうか?)

関連するQ&A

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

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

  • new と malloc によるメモリの動的確保について

    初めて投稿させて頂きます。よろしくお願い致します。 現在、以下のような、2次元配列による動的なメモリの確保を意図して、コードをC/C++にて記述しています。 (コンパイラはMINGW32のg++ 3.4.5) //mallocによるメモリ動的確保 data = (char **)malloc(num * sizeof(char*)); for(i=0; i<rowNum; i++){ data[i] = (char *)malloc(sizeof(char)*256); } //newによるメモリ動的確保 data = new char*[rowNum]; for(i=0; i<rowNum; i++){ data[i] = new char; } C++で書くのならば、 「mallocによるメモリ確保は辞め、newによるメモリ確保をしなさい」 という指摘が、書籍でもwebでもありましたので、 両方書き、両者を比べているのですが、理由がイマイチ分かりません。 10万行ほどのテキストデータで実験させてみたのですが、 mallocによる記述の方が、動作が数秒速いようなのです。 それで、new やmalloc で実際何をやっているのか、コードを見ようと思ったのですが、 newでは、 void* operator new(std::size_t) throw (std::bad_alloc); void* operator new[](std::size_t) throw (std::bad_alloc); void* operator new(std::size_t, const std::nothrow_t&) throw(); void* operator new[](std::size_t, const std::nothrow_t&) throw(); inline void* operator new(std::size_t, void* __p) throw() { return __p; } inline void* operator new[](std::size_t, void* __p) throw() { return __p; } というnewファイルの記述で行き詰まり、 malloc は malloc_allocator.hというファイルで行き詰りました。 以上を踏まえて、 1)そもそも、上記のメモリ動的確保記述はスマートな書き方なのか 2)実際に、newやmallocは、どういった手法でメモリ領域を確保しているのか 以上の2点について、ご教授下さい。よろしくお願い致します。

  • malloc関数 free開放とはなんですか?

    malloc関数を用いてメモリを確保した後、 必ずfreeで開放を行わなければならないですよね? この開放とはどういう意味なのでしょうか?

  • 組み込み系でのmallocについて

    組み込み系について勉強しいます。 組み込み系ではサイズが決まっている場合、一度mallocすればfreeはしないと誰かが言ったのを聞いたのですがどういうことですか? 電源を切る=メモリ開放 ということですか? よろしくおねがいします。

  • mallocについて

    vine linux 3.0上でgccを使い下記のようなプログラム(読みにくいプログラムで申し訳ありません)を作成してみました。無事コンパイルも通りメモリも確保出来ました。 しかし、このプログラムを2つ起動しそれぞれでメモリを確保するとおかしな事が起きるのです。どういう症状かと言うとプログラム1もプログラム2も同じ先頭アドレスを確保しているのです。 例) プログラム1 keep memory size : 11 address : 0x8049700 プログラム2 keep memory size : 11 address : 0x8049700 なぜこのような事が起こるのでしょうか? ご教授宜しくお願いします。 #include <stdio.h> #include <stdlib.h> main(int argc, char *argv[]) { int size; unsigned int *p; char buf; size = atoi(argv[1]); printf("keep memory size : %d\n", size); p = (unsigned int *)malloc(size); printf("address : %p\n", p); scanf("%c", &buf); free(p); }

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

    テキストファイルを読込む関数を作成しています。 まず最初にある程度の領域を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とfree

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

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

    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関数の使い方について(初心者)

    膨大なデータ数を扱うためにmalloc関数を用いて配列にデータを格納し、それを表示するプログラムを考えました。コンパイルはできるのですが、実行するとエラーが起こります。freeの開放の仕方が間違っているのでしょうか?よろしくお願いします。 /*ソース*/ #include <stdio.h> #include <stdlib.h> #define N 130000 int main(void) { double *p; int i; p = malloc(N); if(!p){ printf("割り当てエラー"); exit(1); } for(i=0;i<N;i++){ p[i]=i; printf("%f\n",p[i]); } free(p); }

  • 文字型配列の有効期間

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