Home > Software engineering >  Points returned by memory allocation functions
Points returned by memory allocation functions

Time:06-04

I am learning C from the book by K.N.King and am going through the programming projects for chapter 17. I came across a self inflicted bug while I was completing the first project. It was undefined behaviour of the program since I was passing realloc() a copy of a pointer returned from an earlier malloc() call, since the realloc() call was occurring in a function other than main(). After re-reading parts of the chapter I realised that realloc() has undefined behaviour in this case.

I have tried to search why this is the case to no avail. So does anyone here know why the pointer passed to realloc() must be a pointer returned from an earlier call of malloc(), calloc() or realloc() and not a copy of these? Also, aren't we inherently always making a copy of a pointer returned by realloc() whenever we want to resize a memory block?

int num_parts = 0, max_parts = 10;

int main(void)
{
    struct part *inventory = malloc(max_parts * sizeof(*inventory));
    \\...
    switch(ch) {
        \\...
        case 'i':
            insert(inventory, &num_parts, &max_parts);
            break;
        \\...
    }
}

void insert(struct part *inventory, int *num_parts, *max_parts)
{
    if (*num_parts == *max_parts) {
        *max_parts  = 10;
        struct part *temp = realloc(inventory, max_parts * sizeof(*temp));
        if (temp != NULL)
            inventory = temp;
        else
            printf("Error:...\n");
    }
    \\...
}

CodePudding user response:

The function insert accepts the pointer inventory by value

void insert(struct *inventory, int *num_parts, *max_parts)

and

insert(inventory, &num_parts, &max_parts);

It means that the function deals with a copy of the the value of the original pointer. Changing the copy within the function like

    if (temp != NULL)
        *inventory = temp;

does not influence on the value of the original pointer declared in main.

You need to pass the pointer by reference through a pointer to it.

That is

insert( &inventory, &num_parts, &max_parts);

And the function will look like

void insert(struct **inventory, int *num_parts, *max_parts)
{
    if (*num_parts == *max_parts) {
        *max_parts  = 10;
        struct part *temp = realloc( *inventory, max_parts * sizeof(*temp));
        if (temp != NULL)
            *inventory = temp;
        else
            printf("Error:...\n");
    }
    \\...
}

In this case dereferencing the function parameter struct **inventory within the function we can get a direct access to the original pointer (object) and thus can change it.

  • Related