【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は謹んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.19514

領域確保と領域開放について
投稿者---慧(2005/01/26 16:44:29)



メインの位置で、領域を確保する変数を宣言し、関数にて領域を確保し
値を設定して、領域を返そうとしているのですが、上手く返却されませ
ん。
領域を確保しているとことでは、正しく値が格納されているのですが、
戻った先では、NULLとなります。
fun_start(str,10) ;

fun_start(&str,10) ;
とするとコアダンプしてしまいます。
何がいけないのでしょうか。

また、free()について聞きたいのですが、
free()は、領域を開放するだけであって、malloc()やrealloc()によって
確保された領域の先の中身までも開放(破棄)してくれるわけではないの
ですね。
プログラムが終了しないかぎりは、なんどでも参照できるものなのでしょ
うか。
もし、そうであった場合、参照できないようにするにはどうしたらよいの
ですか。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int fun_start(char **, int) ;
int fun_disp(char **, int) ;

main()
{
    char **str = NULL ;
    int  i ;

    fun_start(str,10) ;
    fun_disp(str,10) ;

    printf("\nmalloc領域解放\n")  ;
    for(i=0; i<10; i++) {
        free(str[i]) ;
    }
    free(str) ;
}
int fun_start(char **str,int num)
{
    char buf[1024] ;
    int size = 1024 ;
    int n = 0, i,j ;

    for(i=0 ; i<num ; i++) {
        if (str == NULL || n >= size) {
            str = realloc(str, (size *= 2) * sizeof(char *)) ;
            if (str == NULL) return puts("out of memory"), 1 ;
        }

        memset(buf,'\0',sizeof(buf)) ;
        memset(buf,'a',i+1) ;

        str[n] = strdup(buf) ;
        if (str[n] == NULL) return puts("out of memory"), 1 ;
        n++ ;
    }
}

int fun_disp(char **str,int num)
{
    int i ;

    for(i=0  ; i<num  ; i++) {
        printf("[%s]\n",str[i]) ;
    }
}



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:領域確保と領域開放について 19516 REE 2005/01/26 17:12:50
<子記事> Re:領域確保と領域開放について 19519 Craft 2005/01/26 19:36:35
<子記事> Re:領域確保と領域開放について 19524 nop 2005/01/26 21:01:42


No.19516

Re:領域確保と領域開放について
投稿者---REE(2005/01/26 17:12:50)


>メインの位置で、領域を確保する変数を宣言し、関数にて領域を確保し
>値を設定して、領域を返そうとしているのですが、上手く返却されませ
>ん。
>領域を確保しているとことでは、正しく値が格納されているのですが、
>戻った先では、NULLとなります。

>何がいけないのでしょうか。

引数は、値渡しです。
関数内のstrはmainのstrをコピーしたものですので、
関数内のstrをいくら変更してもmainのstrは変わりません。

fun_startの引数の型をchar ***にして、fun_start(&str,10) ;
の様に呼び出す必要があります。
(もちろんfun_startの中身もそれにあわせて変更が必要です。)


>また、free()について聞きたいのですが、
>free()は、領域を開放するだけであって、malloc()やrealloc()によって
>確保された領域の先の中身までも開放(破棄)してくれるわけではないの
>ですね。

「領域の先の中身」は何を指しているのでしょうか?



この投稿にコメントする

削除パスワード

No.19520

Re:領域確保と領域開放について
投稿者---慧(2005/01/26 19:44:01)


ご指摘ありがとうございます。

>fun_startの引数の型をchar ***にして、fun_start(&str,10) ;
>の様に呼び出す必要があります。
>(もちろんfun_startの中身もそれにあわせて変更が必要です。)
を直しましたら、一応、一通り、動くものになりました。

fun_start()内で、領域を確保し、確保した領域のアドレスを返す
ようにしましたが、引数と使用している「str」を使用して上手く
することはできないのでしょうか。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int fun_start(char ***, int) ;
int fun_disp(char **, int) ;

main()
{
    char **str = NULL ;
    int  i ;

    fun_start(&str,10) ;
    fun_disp(str,10) ;

    printf("\nmalloc領域解放\n")  ;
    for(i=0; i<10; i++) {
        free(str[i]) ;
    }
    free(str) ;
}
int fun_start(char ***str,int num)
{
    char **temp ;
    char buf[1024] ;
    int size = 1024 ;
    int n = 0, i,j ;

    for(i=0 ; i<num ; i++) {
        if (temp == NULL || n >= size) {
            temp = realloc(temp, (size *= 2) * sizeof(char *)) ;
            if (temp == NULL) return puts("out of memory"), 1 ;
        }

        memset(buf,'\0',sizeof(buf)) ;
        memset(buf,'a',i+1) ;

        temp[n] = strdup(buf) ;
        if (temp[n] == NULL) return puts("out of memory"), 1 ;
        n++ ;
    }
    *str = temp ;
}

int fun_disp(char **str,int num)
{
    int i ;

    for(i=0  ; i<num  ; i++) {
        printf("[%s]\n",str[i]) ;
    }
}




この投稿にコメントする

削除パスワード

No.19523

Re:領域確保と領域開放について
投稿者---REE(2005/01/26 20:39:00)


>fun_start()内で、領域を確保し、確保した領域のアドレスを返す
>ようにしましたが、引数と使用している「str」を使用して上手く
>することはできないのでしょうか。

「上手くする」とは?
何を求めているのか分かりませんので、具体的に相談してください。



この投稿にコメントする

削除パスワード

No.19530

Re:領域確保と領域開放について
投稿者---慧(2005/01/26 22:43:04)


fun_start()についてです。
変数tempで領域を確保し、引数で渡されたstrにアドレスを入れて
いますが、一時的に退避するのではなく、直接strに入れて操作す
ることはできますか。

また、nopさんの書き込みで、
>> str = realloc(str, (size *= 2) * sizeof(char *)) ;
>
>realloc() に失敗した場合、
>失敗前に渡した領域は解放されません。
>なので、この様な realloc() の使用は、
>メモリリークの危険がありやめた方が良いでしょう。
どう改善したら良い方法になりますか。?

int fun_start(char ***str,int num)
{
    char **temp ;
    char buf[1024] ;
    int size = 1024 ;
    int n = 0, i,j ;

    for(i=0 ; i<num ; i++) {
        if (temp == NULL || n >= size) {
            temp = realloc(temp, (size *= 2) * sizeof(char *)) ;
            if (temp == NULL) return puts("out of memory"), 1 ;
        }

        memset(buf,'\0',sizeof(buf)) ;
        memset(buf,'a',i+1) ;

        temp[n] = strdup(buf) ;
        if (temp[n] == NULL) return puts("out of memory"), 1 ;
        n++ ;
    }
    *str = temp ;
}






この投稿にコメントする

削除パスワード

No.19537

Re:領域確保と領域開放について
投稿者---HALLS(2005/01/26 23:42:17)


>fun_start()についてです。

tempに何も値をセットしていない状態でNULLと比較して
大丈夫でしょうか。

>どう改善したら良い方法になりますか。?

realloc()に失敗してtempにNULLが入ると、
もともとtempが指していた領域をアクセスしたり開放したり
できなくなってしまうことがまずいのではないでしょうか。


この投稿にコメントする

削除パスワード

No.19542

Re:領域確保と領域開放について
投稿者---HALLS(2005/01/27 07:58:02)


>tempに何も値をセットしていない状態でNULLと比較して

「何も値をセットしていない状態」よりは、
「明示的に値をセットしていなくてゴミが入っている状態」と
いう方がより正確であるようですね。



この投稿にコメントする

削除パスワード

No.19545

Re:領域確保と領域開放について
投稿者---REE(2005/01/27 09:46:46)


>fun_start()についてです。
>変数tempで領域を確保し、引数で渡されたstrにアドレスを入れて
>いますが、一時的に退避するのではなく、直接strに入れて操作す
>ることはできますか。

出来ます。
tmpを*strに置き換えればよいです。


この投稿にコメントする

削除パスワード

No.19568

Re:領域確保と領域開放について
投稿者---慧(2005/01/27 14:52:18)


>出来ます。
>tmpを*strに置き換えればよいです。
ですか。?
ポインタのポインタのポインタになってしまいわからなく
なってしまったようです。
でも、*strになるのでしょうか。


この投稿にコメントする

削除パスワード

No.19572

Re:領域確保と領域開放について
投稿者---REE(2005/01/27 15:13:20)


>でも、*strになるのでしょうか。

そのまんまですが何が分からないのでしょう?

int fun_start(char ***str,int num)
{
    char buf[1024] ;
    int size = 1024 ;
    int n = 0, i,j ;

    for(i=0 ; i<num ; i++) {
        if (*str == NULL || n >= size) {
            *str = realloc(*str, (size *= 2) * sizeof(char *)) ;
            if (*str == NULL) return puts("out of memory"), 1 ;
        }

        memset(buf,'\0',sizeof(buf)) ;
        memset(buf,'a',i+1) ;

        (*str)[n] = strdup(buf) ;
        if ((*str)[n] == NULL) return puts("out of memory"), 1 ;
        n++ ;
    }
}





この投稿にコメントする

削除パスワード

No.19582

Re:領域確保と領域開放について
投稿者---慧(2005/01/27 16:10:02)


***str 宣言されている変数が

if (*str == NULL || n >= size) {
(*str)[n] = strdup(buf) ;
となることです。

str
*str
**str
***str
がこんがらっています。

また、
free()後に、fun_startとfun_dispを実行したら
coreをはいたのですが、領域の再利用ができない
でしょうか。
free()は、最後がいいんでしょうか。


この投稿にコメントする

削除パスワード

No.19599

Re:領域確保と領域開放について
投稿者---慧(2005/01/27 21:01:52)


***strで受け取ったものが*strで使える。
(*str)[n]で入力できる。

str
*str
**str
***str
がこんがらっています。

また、
free()後に、fun_startとfun_dispを実行したら
coreをはいたのですが、領域の再利用ができない
でしょうか。
free()は、最後がいいんでしょうか。


この投稿にコメントする

削除パスワード

No.19519

Re:領域確保と領域開放について
投稿者---Craft(2005/01/26 19:36:35)


>また、free()について聞きたいのですが、
>free()は、領域を開放するだけであって、malloc()やrealloc()によって
>確保された領域の先の中身までも開放(破棄)してくれるわけではないの
>ですね。

掲示されたソースから推測して、
char **p = malloc( sizeof(char *) * 10 );
で 10個の (char *) の領域を確保して、続けて
*(p+1) = malloc( sizeof(char) * 5 );
として、文字列格納用の領域を確保した場合に、
free( p ) とした場合のことをおっしゃっているのであれば、
free()は、そのメモリが何の用途につかわれていたかまでは関与しませんので、当然 *(p+1) のポインタにセットしたメモリは解放されません。

長くなってわかりにくなってしまったかもしれません。


この投稿にコメントする

削除パスワード

No.19524

Re:領域確保と領域開放について
投稿者---nop(2005/01/26 21:01:42)


> str = realloc(str, (size *= 2) * sizeof(char *)) ;

realloc() に失敗した場合、
失敗前に渡した領域は解放されません。
なので、この様な realloc() の使用は、
メモリリークの危険がありやめた方が良いでしょう。


この投稿にコメントする

削除パスワード

No.19529

Re:領域確保と領域開放について
投稿者---慧(2005/01/26 22:42:28)


free()で領域解放をしても、printf()で表示ができました。
領域解放すると、領域が見えなくなり(参照できなくなり)、
確保された領域に入れられた値が破棄されると思っているの
ですが、違うのですか。

>realloc() に失敗した場合、
>失敗前に渡した領域は解放されません。
>なので、この様な realloc() の使用は、
>メモリリークの危険がありやめた方が良いでしょう。
どう改善したら良い方法になりますか。?



この投稿にコメントする

削除パスワード

No.19539

Re:領域確保と領域開放について
投稿者---NykR(2005/01/27 00:11:11)


>free()で領域解放をしても、printf()で表示ができました。
>領域解放すると、領域が見えなくなり(参照できなくなり)、
>確保された領域に入れられた値が破棄されると思っているの
>ですが、違うのですか。

free()はmalloc()で確保した領域を解放し、再びmalloc()で同じ領域を確保できるようにするための(そのためだけの)関数です。
ですから、free()で領域解放をしても、そこにあるデータが破壊されるという保証はありません(破壊されないという保証もありませんが)。
また、その領域を指していたポインタがその領域を指さなくなる、という保証もありません(指しっぱなしという保証もありませんが)。
領域を再利用できるようになるだけです。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧