• ベストアンサー

mallocについて

まだ初心者で分からないところがあるのですが 例えば char *Buf; Buf=(char *)malloc(256); free(Buf); としますよね? それを、 グローバル変数(?)で「char *Buf」として 処理の途中途中で Buf=(char *)malloc(*適当) を、何回も使い 最後の解放されるときに free(Buf) (*適当 は、適当な数値) を使う事は大丈夫でしょうか? それとも、ちゃんとメモリを割り当て(?)たら 使ったあとすぐに、メモリを解除しなければ ならないのですか? よろしくお願いしますm(_ _)m

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

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

 基本的には、#2さんのとおりですが・・・  ちょっと気になったので補足を。  たとえば、mainの先頭で、  Buf=(char *)malloc(十分大きな値)  を実行して、このメモリーを、その後、プログラム全域でずっと使い続ける。という使い方はありです。メモリーの確保というのは、意外と重たい処理なので、開放と確保の作業の繰り返しがあまりにも多いときには、この手を使用することがあります。  しかし・・・  決して、同じBufに対して、freeを実行することなくmallocを2回以上実行してはいけません。一度、グローバル変数Bufに保管したメモリー領域は、freeを実行するまでずっと有効です。そこに、もう一度、  Buf=(char*)malloc(適当)  を実行すると、この文を実行する前に確保されていたメモリーが迷子になります。そこに確保したメモリーは相変わらず確保されたままあるのですが、アドレスをメモしておいたBufを上書きしたので、もうそこにアクセスできなくなったと言う状態です。(freeに与える引数にする値も失われたので、もう開放することもできません)  この状態を、メモリーリークと称します。Cのプログラムでよく発生する「バグ」です。何度も繰り返して、迷子のメモリーの量が多くなると、メモリー不足でプログラムの続行ができなくなる・・・という結果になります。  注意してくださいね。

dinowave
質問者

お礼

長い解答ありがとうございます あ!また別なんですが、これで不思議な謎が解けました! どうしてテストを繰り返してる最中に プログラムがおかしくなるのか、わからなかったのですが こういうことだったんですね いろいろと参考になりました ありがとうございますm(_ _)m

その他の回答 (3)

  • symgt
  • ベストアンサー率56% (68/120)
回答No.3

処理の途中で確保したメモリのサイズを変更したいのであれば realloc()を使用しましょう。 char *p; p = (char *)malloc(10); p = (char *)realloc(p, 20); p = (char *)realloc(p, 30); free(p);

dinowave
質問者

お礼

あ、ちゃんと書いておけばよかったですね... メモリのサイズを変更したのではなく ただ単にメモリを初期化(?)したかっただけなのです だけど、reallocのことを忘れてて 丁度良く思い出せました ありがとうございますm(_ _)m

  • mcWalker
  • ベストアンサー率69% (27/39)
回答No.2

tatsu99 さんの応えが基本ですが、global で、 テーブル類を固定長で、沢山定義するようなら、 main() の最初に確保して、出口で必ず解放する のも手です。よく見る方法は、main() の出口に cleanup: というラベルを付け、エラーなどの場合 全てそこへ goto させ、cleanup: で解放するわけ です。Cでは goto は嫌われますが、これも手です。   領域用のポインタは必ず初期値を NULL にして   おいて出口で NULLでなければ解放するとか、   逐次解放したら即 NULL にするとかして解放   洩れを防ぎます。 全部で 100 x 5 の領域が必要なら、500 で取って、 先頭+100, 先頭+200、のポインタを使う手もあります。 malloc(), free() を繰り返すと断片化が起きるの 防げます。(断片化防止には GlobalAlloc() などの API を MOVEABLE で使う手もあります。Mac なら、 NewHandle()) 蛇足ですが、メモリの少ない時代には、エラー処理用に forRainyDay という名前でメモリ領域を確保して置き、 メモリ不足に陥ると、ここを使って状況を表示するとか していました。

dinowave
質問者

お礼

あー、なるほど、そういうやりかたもあるんですねぇ forRainyDay、なんかこういう系統好きなんで 覚えておきます♪ ありがとうございますm(_ _)m

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.1

>グローバル変数(?)で「char *Buf」として >処理の途中途中で Buf=(char *)malloc(*適当) >を、何回も使い >最後の解放されるときに free(Buf) >(*適当 は、適当な数値) >を使う事は大丈夫でしょうか? 前に割り当てられたメモリが解放されないで残ります。 これが、思わぬバグを招くことになります。 >それとも、ちゃんとメモリを割り当て(?)たら >使ったあとすぐに、メモリを解除しなければ >ならないのですか? 必ずそのようにしてください。

dinowave
質問者

お礼

なるほど、...わかりました ありがとうございますm(_ _)m

関連するQ&A

  • malloc後、frokを行った場合

    unix(Solaris)系、CCコンパイラ初心者です。 質問内容は2点あります。 1点目 たとえば変数Aを親プロセスでmallocを行い、その後forkした場合は 変数Aは子プロセスにも引き継がれると思いますが、 解放する場合は親、子プロセス両方でfreeする必要はあるのでしょうか? 2点目 1点目のmallocした変数Aをshmで共有メモリにした場合は 親又は子どちらか片方でfreeすればよろしいのでしょうか? よろしくお願いします。

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

    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を使って動的にメモリーの確保、開放を行っているのですが、途中で暴走してしまいます。 (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関数等を自作とかされていますでしょうか?  どうぞよろしくお願い致します。

  • 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がうまく動かない

    コマンドライン引数で指定された文字列を逆順に返すプログラムを作るため 下記のようなプログラムを組みました。 ところが変数strの大きさがargv[1]より大きくなってしまいます。 どうすればよいのでしょうか。 #include <stdio.h> #include <stdlib.h> char *mstrrev (char *s); int main(int argc, char *argv[]){ char *str; str = mstrrev(*(argv+1)); printf("%s",str); free(str); } char *mstrrev (char *s){ int length,i; char *str; for(length=0;*(s+length)!='\0';length++); str = (char *)malloc(sizeof(char)*length); for(i=0;i<length;i++){ str[i] = s[length-1-i]; } return str; }

  • mallocで確保したメモリをfree解放する必要

    当方、C言語を勉強中です。 mallocで確保しておいたメモリをfreeで必ず解放するようにと教わりました。 freeで開放しないことをひどく野蛮な言葉で例えられたのですが、それほどまでに必要である実感が実はあまりありません。 ファイルポインタでファイルを開いているときに、プログラムが終了すると開いているファイルを自動的に閉じるように、プログラムが終了すると自動的に解放されるものと思っていたのですが、やはりこちらはプログラム終了後も確保されたままになってしまうのでしょうか。 また、解放しないことによるデメリットで、メモリを圧迫する以外にはなにがあるのでしょうか。 ご教授おねがいします。

  • malloc使用後のメモリアロケーションエラー(MS-C7.0)

    初めて投稿させていただきます。 現在PC:98 OS:MS-DOS 言語:MS-C7.0のhugeモデル という環境で プログラミングを行っております。しかし、config.sys,autoexec.batを 工夫してもメモリ不足を補えず、変数と動的にすることにしました。 c言語のテキストを参考に kansu() { char *p; p=(char *)malloc(256*256*sizeof(char)); if(p=null) printf("メモリ確保に失敗"); ・ ・ free(p); } とすると kansu終了直後に"メモリアロケーションエラー"がでます。 自分ではどこが悪いのわからず、ここでお聞きすることにしました。 上記の中の原因、もしくは原因と考えられることを教えてください。 よろしくおねがいします。

  • メモリ操作関数『malloc(),free()』

    /*10バイトのメモリ領域を確保し、その領域に文字列"Allocate"を代入せよ。*/ /*ただし、確保した領域は、プログラム終了までに開放すること。*/ #include<stdio.h> #include<stdlib.h> void main(void) { char *ptr; ptr = (char *)malloc(10); printf("Allocate\n"); free(ptr); } 今、ライブラリ関数を勉強しています。 この問題をとりあえず作ってみて、実行も成功したのですが、10バイトのメモリ確保の数値を変えても、何も変わらないため本当に問題の要求どおりのプログラムが作れているのか謎です。 間違っているなどのアドバイス宜しくお願いします。

  • c言語のmalloc関数、またrealloc関数

    c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。

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

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