rainmaker
rainmaker

Reputation: 303

realloc array of pointers

This is part of my program. parameters.path is a string that contains a path to the file I will be working with, but that is not in this code.

typedef struct directory {

   char *name;
   char *path;

} directory;

void insertDir(directory*** array , char * path, char* name, int* length) {

    directory *p = malloc(sizeof(directory));

    p->path = malloc(strlen(path)+ 1);
    strcpy(p->path, path);

    p->name = malloc(strlen(name)+ 1);
    strcpy(p->name, name);

    *array = (directory**) realloc( *array , (*length) * (sizeof(directory*)));
    *array[(*length)] = p;
    (*length)++;

}

int main(int argc , char** argv) {

    directory** array = NULL;

    int lenght = 0;

    while(true) {
        insertDir(&array, parameters.path, name , &lenght);
    }

    return 0;
}

It fails on the third realloc with segmentation fault. Can you help me please?

Upvotes: 1

Views: 11009

Answers (2)

David C. Rankin
David C. Rankin

Reputation: 84561

In addition to the (*array)[*length] indexing issue, you leave yourself wide open for several allocation failures with both malloc and realloc. First, and generally, always validate that your allocation succeeds. Enough said.

Next, with realloc, it is always better to reallocate using a temporary variable instead of your array. If there is a failure on reallocation, realloc returns NULL causing you to lose the address to array completely. This will cause the loss of all existing data. Instead, if you use a tmp pointer for reallocation, you have the ability to handle the failure in a graceful manner, and the ability to free the block of memory originally assigned to array.

Here is a bit more robust way to handle the allocations/reallocations. Note: you are left to code the response to a reallocation failure:

void insertDir (directory*** array, char *path, char *name, int *length)
{

    directory *p = malloc (sizeof *p);
    if (!p) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }

    p->path = malloc (strlen (path) + 1);
    strcpy (p->path, path);

    p->name = malloc (strlen (name) + 1);
    strcpy(p->name, name);

    directory **tmp = realloc (*array, (*length + 1) * sizeof *tmp);
    if (!tmp) {
        fprintf (stderr, "error: struct reallocation failure.\n");
        exit (EXIT_FAILURE);
    }
    *array = tmp;
    (*array)[*length] = p;
    (*length)++;

}

Upvotes: 3

Barmar
Barmar

Reputation: 780974

When doing the realloc(), you need to add 1 to the length, because you haven't incremented it yet.

*array = realloc( *array , (*length + 1) * (sizeof(directory*)));

You also need to change:

*array[(*length)] = p;

to:

(*array)[*length] = p;

because the subscripting operator has higher precedence than the dereference operator. See the C operator precedence table here. There's also no need for parentheses inside [].

Upvotes: 6

Related Questions