开发者

How to realloc an array inside a function with no lost data? (in C )

开发者 https://www.devze.com 2023-02-01 18:44 出处:网络
I have a dynamic array of structures, so I thought I could store the information about the array in the first structure.

I have a dynamic array of structures, so I thought I could store the information about the array in the first structure.

So one attribute will represent the amount of memory allocated for the array and another one representing number of the structures actually stored in the array.

The trouble is, that when I put it inside a function that fills it with these structures and tries to allocate more memory if needed, the original array gets somehow distorted.

Can someone explain why is this and how to get past it? Here is my code

#define INIT 3

typedef struct point{
    int x;
    int y;
    int c;
    int d;
}Point;
Point empty(){
    Point p;
    p.x=1;
    p.y=10;
    p.c=100;
    p.d=1000; //if you put different values it will act differently - weird
    r开发者_StackOverflow社区eturn p;
}
void printArray(Point * r){
    int i;
    int total = r[0].y+1;
    for(i=0;i<total;i++){
          printf("%2d | P [%2d,%2d][%4d,%4d]\n",i,r[i].x,r[i].y,r[i].c,r[i].d);
    }
}

void reallocFunction(Point * r){
    r=(Point *) realloc(r,r[0].x*2*sizeof(Point));
    r[0].x*=2;
}
void enter(Point* r,int c){
    int i;
    for(i=1;i<c;i++){
        r[r[0].y+1]=empty();
        r[0].y++;
        if( (r[0].y+2) >= r[0].x ){ /*when the amount of Points is near
                                     *the end of allocated memory.
                                      reallocate the array*/
            reallocFunction(r);
        }
    }
}

int main(int argc, char** argv) {
    Point * r=(Point *) malloc ( sizeof ( Point ) * INIT );
    r[0]=empty();
    r[0].x=INIT;    /*so here I store for how many "Points" is there memory
                    //in r[0].y theres how many Points there are.*/
    enter(r,5);
    printArray(r);
    return (0);
}


Your code does not look clean to me for other reasons, but...

void reallocFunction(Point * r){
    r=(Point *) realloc(r,r[0].x*2*sizeof(Point));
    r[0].x*=2;
    r[0].y++;
}

The problem here is that r in this function is the parameter, hence any modifications to it are lost when the function returns. You need some way to change the caller's version of r. I suggest:

Point *   // Note new return type...
reallocFunction(Point * r){
    r=(Point *) realloc(r,r[0].x*2*sizeof(Point));
    r[0].x*=2;
    r[0].y++;

    return r; // Note: now we return r back to the caller..
}

Then later:

r = reallocFunction(r);

Now... Another thing to consider is that realloc can fail. A common pattern for realloc that accounts for this is:

Point *reallocFunction(Point * r){
    void *new_buffer = realloc(r, r[0].x*2*sizeof(Point));

    if (!new_buffer)
    {
       // realloc failed, pass the error up to the caller..
       return NULL;
    }

    r = new_buffer;
    r[0].x*=2;
    r[0].y++;

    return r;
}

This ensures that you don't leak r when the memory allocation fails, and the caller then has to decide what happens when your function returns NULL...

But, some other things I'd point out about this code (I don't mean to sound like I'm nitpicking about things and trying to tear them apart; this is meant as constructive design feedback):

  • The names of variables and members don't make it very clear what you're doing.
  • You've got a lot of magic constants. There's no explanation for what they mean or why they exist.
  • reallocFunction doesn't seem to really make sense. Perhaps the name and interface can be clearer. When do you need to realloc? Why do you double the X member? Why do you increment Y? Can the caller make these decisions instead? I would make that clearer.
  • Similarly it's not clear what enter() is supposed to be doing. Maybe the names could be clearer.
  • It's a good thing to do your allocations and manipulation of member variables in a consistent place, so it's easy to spot (and later, potentially change) how you're supposed to create, destroy and manipulate one of these objects. Here it seems in particular like main() has a lot of knowledge of your structure's internals. That seems bad.
  • Use of the multiplication operator in parameters to realloc in the way that you do is sometimes a red flag... It's a corner case, but the multiplication can overflow and you can end up shrinking the buffer instead of growing it. This would make you crash and in writing production code it would be important to avoid this for security reasons.


You also do not seem to initialize r[0].y. As far as I understood, you should have a r[0].y=0 somewhere.

Anyway, you using the first element of the array to do something different is definitely a bad idea. It makes your code horribly complex to understand. Just create a new structure, holding the array size, the capacity, and the pointer.

0

精彩评论

暂无评论...
验证码 换一张
取 消