2

realloc()いくつかの配列を動的にサイズ変更するために使用しています。私は次のようなコードをたくさん書いていたからです:

void *tmp;
if( (tmp = realloc(myobject, sizeof(object) * newsize) != NULL)
         myobject = tmp

次のようなことをしてコードを短くしようと思いました (ばかげた考え):

void GetSpace(void *ptr, size_t size_of_object, int newsize){
    void *tmp = NULL;
    if ((tmp = realloc(ptr, size_of_object * newsize) == NULL)
          //print error msg and exit
    else 
         ptr = tmp;
}
int main(){
    //This is an example
    double *mydata1 = (double *)malloc (sizeof double * 5);


    //later request more space for mydata1 
    GetSpace( mydata1, sizeof(double), 50);

}

多くの行を節約したり、コードを読みやすくしたりしないため、これはばかげていますが、期待どおりに機能しない理由を知りたいです。GetSpace()単一のオブジェクトに対してのみ使用すると、正常に機能します。関数を呼び出すオブジェクトを初期化せずにコードを実行すると、問題なく実行されますが、オブジェクトを呼び出してからGetSpace()データを入れてからGetSpace()別のオブジェクトを呼び出すと、次のようなメッセージでスタック トレースが表示されます。

*** glibc detected *** ./a.out: realloc(): invalid old size: 0x00007fff05d96790 ***

0x00007fff05d96790サイズ変更前の 2 番目の配列/オブジェクトのアドレスです。なぜこれが起こるのですか?

4

1 に答える 1

3

関数では、GetSpaceより大きなサイズの新しいメモリ ブロックを割り当て、アドレスをローカル変数に割り当てていますptr。しかし、関数が終了すると、この新しいアドレスは失われます。メイン プログラムには の古い値がまだあり、現在はptr無効な (解放された) メモリを指しています。

新しいアドレスを発信者に返す必要があります。代わりにこれを試してください。ptrパラメータは参照渡しになっているため、呼び出し元の変数が更新されることに注意してください。

void GetSpace(void **ptr, size_t size_of_object, int newsize){
    void *tmp = NULL;
    if ((tmp = realloc(*ptr, size_of_object * newsize) == NULL)
         //print error msg and exit
    else 
         *ptr = tmp;
}

編集:コメントで指摘されているように、これはまだ理想的ではありません。ポインタのアドレスをvoid**. 次のように、新しいポインターを個別に返すことで改善されます。

void *GetSpace(void *ptr, size_t size_of_object, int newsize){
    void *tmp = NULL;
    if ((tmp = realloc(ptr, size_of_object * newsize) == NULL)
        //print error msg and exit
    else 
        return tmp;
}

int main(){

    ...

    //later request more space for mydata1 
    mydata1 = GetSpace( mydata1, sizeof(double), 50);
}
于 2011-08-01T16:07:16.677 に答える