Search code examples
cpointerscrashallocationpointer-to-pointer

crash on trying to reallocate a pointer using pointer to this pointer


I have a pointer to a pointer ("paths") and I want to reallocate each pointer (each "path"). But I get a crash. Generally I am trying to find all possible powers of a number, which one can compute for some amount of operations (e.g for two operations we can get power of three and four (one operation for square of a number, then another one either for power of three or four)). I figured out how to do it on paper, now I am trying to implement it in code. Here is my try:

#include <stdio.h>
#include <stdlib.h>

void print_path(const int *path, int path_length);

int main(void)
{
    fputs("Enter number of operations? ", stdout);
    int operations;
    scanf("%i", &operations);
    int **paths, *path, npaths, npath;
    npaths = npath = 2;
    path = (int*)malloc(npath * sizeof(int));
    paths = (int**)malloc(npaths * sizeof(path));
    int i;
    for (i = 0; i < npaths; ++i)    // paths initialization
    {
        int j;
        for (j = 0; j < npath; ++j)
            paths[i][j] = j+1;
    }
    for (i = 0; i < npaths; ++i)    // prints the paths, all of them are displayed correctly
        print_path(paths[i], npath);

    for (i = 1; i < operations; ++i)
    {
        int j;
        for (j = 0; j < npaths; ++j) // here I am trying to do it
        {
            puts("trying to reallocate");
            int *ptemp = (int*)realloc(paths[j], (npath + 1) * sizeof(int));
            puts("reallocated");    // tried to write paths[j] = (int*)realloc...
            paths[j] = ptemp;   // then tried to make it with temp pointer
        }
        puts("memory reallocated");
        ++npath;
        npaths *= npath;    // not sure about the end of the loop
        paths = (int**)realloc(paths, npaths * sizeof(path));
        for (j = 0; j < npaths; ++j)
            paths[j][npath-1] = paths[j][npath-2] + paths[j][j];
        for (j = 0; j < npaths; ++j)
            print_path(paths[j], npath);

        puts("\n");
    }
    int c;
    puts("Enter e to continue");
    while ((c = getchar()) != 'e');
    return 0;
}

void print_path(const int *p, int pl)
{
    int i;
    for (i = 0; i < pl; ++i)
        printf(" A^%i -> ", p[i]);
    puts(" over");
}

Solution

  • I am not sure the problem resides with the call to realloc(), rather you are attempting to write to locations for which you have not created space...
    Although you create memory for the pointers, no space is created (allocate memory) for the actual storage locations.

    Here is an example of a function to allocate memory for a 2D array of int:

    int ** Create2D(int **arr, int cols, int rows)
    {   
        int space = cols*rows; 
        int    y;
    
        arr   = calloc(space, sizeof(int));
        for(y=0;y<cols;y++)
        {
            arr[y] = calloc(rows, sizeof(int)); 
        }
        return arr;
    }  
    
    void free2DInt(int **arr, int cols)
    {
        int i;
        for(i=0;i<cols; i++)
            if(arr[i]) free(arr[i]);
        free(arr);  
    }
    

    Use example:

    #include <ansi_c.h>
    int main(void)
    {
        int **array=0, i, j;
        array = Create2D(array, 5, 4);
        for(i=0;i<5;i++)
            for(j=0;j<4;j++)
                array[i][j]=i*j; //example values for illustration
        free2DInt(array, 5);
    
        return 0;
    
    }
    

    Another point here is that it is rarely a good idea to cast the return of [m][c][re]alloc() functions

    EDIT

    This illustration shows my run of your code, just as you have presented it: enter image description here

    At the time of error, i==0 & j==0. The pointer at location paths[0][0] is uninitialized.

    EDIT 2
    To reallocate a 2 dimension array of int, you could use something like:

    int ** Realloc2D(int **arr, int cols, int rows)
    {   
        int space = cols*rows; 
        int    y;
    
        arr   = realloc(arr, space*sizeof(int));
        for(y=0;y<cols;y++)
        {
            arr[y] = calloc(rows, sizeof(int)); 
        }
        return arr;
    }    
    

    And here is a test function demonstrating how it works:

    #include <stdio.h>
    #include <stdlib.h>
    
    int ** Create2D(int **arr, int cols, int rows);
    void free2DInt(int **arr, int cols);
    int ** Realloc2D(int **arr, int cols, int rows);
    
    int main(void)
    {
        int **paths = {0};
        int i, j;
    
        int col = 5;
        int row = 8;
    
        paths = Create2D(paths, col, row);
        for(i=0;i<5;i++)
        {
            for(j=0;j<8;j++)
            {
                paths[i][j]=i*j;    
            }
        }
        j=0;
        for(i=0;i<5;i++)
        {
    
            for(j=0;j<8;j++)
            {
                printf("%d ", paths[i][j]); 
            }
            printf("\n");
        }
        //reallocation:
        col = 20;
        row = 25;
    
        paths = Realloc2D(paths, col, row);
        for(i=0;i<20;i++)
        {
            for(j=0;j<25;j++)
            {
                paths[i][j]=i*j;    
            }
        }
        j=0;
        for(i=0;i<20;i++)
        {
    
            for(j=0;j<25;j++)
            {
                printf("%d ", paths[i][j]); 
            }
            printf("\n");
        }
    
        free2DInt(paths, col);
    
        getchar();
        return 0;
    }