mallocで確保した領域の後に続けてreallocで領域を作るには?

解決


Mamoru  2006-02-27 11:28:37  No: 60816  IP: [192.*.*.*]

int* p = (int*)malloc(sizeof(int)*10)をして
mallocで確保した領域の後に続けてreallocをしたいのですが
reallocにはmallocで確保したポインタを渡してあげないといけないみたいです。
reallocでmallocの確保したアドレスの最後の所から領域を作るにはどうしたらいいのでしょうか?

編集 削除
みい  2006-02-27 11:44:46  No: 60817  IP: [192.*.*.*]

移動せずに拡張したいという意味であれば、_expandでサイズを変更できます。

編集 削除
KING・王  2006-02-27 12:24:25  No: 60818  IP: [192.*.*.*]

> reallocでmallocの確保したアドレスの最後の所から領域を作るにはどうしたらいいのでしょうか?

mallocで確保した領域の次の部分を他の部分で使用されていたら・・・
などを考えると、無理なのでは?

編集 削除
Mamoru  2006-02-27 13:59:47  No: 60819  IP: [192.*.*.*]

早い返信ありがとうございます。
_expandを使ってみたのですが、ブレークポイントのエラーが出てしまいました。
よくmallocをして領域が足りない時はreallocで確保したらいいと言われますが、それはmallocで確保した領域をインクリメントや+=SIZEを使ってreallocが確保した領域をアクセスして使っていくということなのでしょうか?
説明が下手ですいません。

編集 削除
REE  2006-02-27 14:28:53  No: 60820  IP: [192.*.*.*]

ブレークポイントのエラー  って何でしょう?

reallocで、領域を確保しなおした時は、新しい領域へのポインタが得られます。
そして、元々mallocで確保していた領域の“代わり”にその新しい領域を使います。

元の領域に入っていたデータと同じものが、新しい領域にも入っていますので、データが失われる心配はいりません。(サイズを大きくした場合)

編集 削除
REE  2006-02-27 14:35:40  No: 60821  IP: [192.*.*.*]

補足
 reallocで渡すサイズは、変化するサイズではなく、変化した後のサイズです。
 reallocに成功した場合、元の領域は解放されて使えなくなります。

編集 削除
Mamoru  2006-02-27 14:41:10  No: 60822  IP: [192.*.*.*]

>ブレークポイントのエラー  って何でしょう?
すいません。_expandに失敗した時にダイアログで出てくるやつです。
先頭アドレスと最後を指しているポインタを入れてみたのですがダメでしたのでreallocでどうにかしようと考えています。

>reallocで、領域を確保しなおした時は、新しい領域へのポインタが得られます。
>そして、元々mallocで確保していた領域の“代わり”にその新しい領域を使います。
代わりに使うのですか。増やすものだと思っていました。

>元の領域に入っていたデータと同じものが、新しい領域にも入っていますので、データが失われる心配はいりません。(サイズを大きくした場合)

新しい領域なのですがmallocで確保した値が入っていて、上書きするような感じなのでそれを避けるために、mallocの後にreallocを使いデータを追加したいと思っています。
しかしながらその上書きも、書き込み時にエラーが出てしまうのでmemsetでゼロクリアしてみたところ書き込めるようになりました。

たとえばmalloc(10)した後にrealloc(20)をしたとしましたら、使える領域の合計は20ですよね?
11から書き込むにはサイズ分飛べばいいということですか?

編集 削除
tetrapod  2006-02-27 15:26:42  No: 60823  IP: [192.*.*.*]

何を訊いているのかさっぱり判らんというのが正直な感想なのですが
malloc/realloc ってそもそも何するものかわかって言ってます?

char *p=malloc(10); // 10byte のメモリを持ってくる
p[9]=0; // OK 10byte 目に値をセット
char *q=realloc(p, 20); // 20byte のメモリを持ってくる
この時点で過去の malloc で返された p はもう使えません。
p と q は別なメモリ領域を指す可能性があります。
p[9]=0; // ダメ もう p の指す先にメモリは無い可能性が有る
q[9]=q[19]=0; // OK

realloc(20) なんて引数の数が合ってませんからできません。
「サイズ分飛ぶ」なんて意味がわからないです。

p の指す先のメモリ容量を変えたいが、アドレスが変わってはならない
という要望に対しては「一般的にそういうことはできない」が答えとなります。

編集 削除
Mamoru  2006-02-27 15:40:49  No: 60824  IP: [192.*.*.*]

>tetrapodさん
申し訳ないです。  
メモリ容量を増やすには
char* p = malloc(10);  の後に
p = realloc(p,20);  とやればいいと勝手に思ってました。
同じ構造体のメモリ容量をとり、同じアドレスが返ってくるので使えると思ってました。
こういった使い方はできないということで解決とさせていただきます。
お目汚しすいませんでした。

編集 削除
Blue  2006-02-27 15:43:41  No: 60825  IP: [192.*.*.*]

サンプル
#include <stdio.h>
#include <malloc.h>

int main( void ){
    int* p;
    int  old_size;
    int  i;
    
    old_size = 10;
    p = ( int* )malloc( old_size * sizeof( int ) );
    if ( p != NULL ){
        int* q;
        int  new_size;
        
        for ( i = 0; i < old_size; i++ )
            p[ i ] = i;
        
        new_size = 20;
        q = ( int* )realloc( p, new_size * sizeof( int ) );
        if ( q != NULL ){
            // reallocに成功した場合、元の領域は解放されて使えなくなる
            // ので、pの値を上書きする
            p = q;
            
            for ( i = old_size; i < new_size; i++ )
                p[ i ] = i;

            // 元の領域に入っていたデータと同じものが、新しい領域にも入っているかの確認
            for ( i = 0; i < new_size; i++ )
                printf( "%d\n", p[ i ] );
        }
        free( p );
    }
    return 0;
}

編集 削除
Blue  2006-02-27 16:03:36  No: 60826  IP: [192.*.*.*]

解決しちゃったのね。。。
更新してから投稿すればヨカツタ。

編集 削除
tetrapod  2006-02-27 16:15:36  No: 60827  IP: [192.*.*.*]

>char* p = malloc(10);  の後に
>p = realloc(p,20);  とやればいいと勝手に思ってました。
realloc の前後で p の値 (すなわち p が指すメモリ) は変わる可能性があります。
realloc が成功するなら提示コードで十分。
失敗する場合に元の p の値が失われてしまうので、リカバリー不能になってしまうですね。
Blue さんのサンプルのように realloc の結果は別の変数に受け取るのが定石です。
realloc の成功を確認した上で p を更新しましょう。

うまくいった場合には (新しいほうの) p が大きくなったメモリ領域を指してますから
p[11] や p[19] をアクセスすることができます。
アドレスが動いても旧データは残っていますから心配しなくて大丈夫。

編集 削除
Mamoru  2006-02-27 16:20:50  No: 60828  IP: [192.*.*.*]

>Blueさん,tetrapodさん
なるほど、ありがとうございます。
ソースが大変わかりやすくて感謝です。
reallocは初めて使うので苦戦しました。
皆様のおかげで本当に解決することができました。
どうもありがとうございました。

編集 削除