0

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");
}
sasha199568
  • 1,143
  • 1
  • 11
  • 33
  • You use a temporary pointer to prevent overwirintg the previous `paths[j]` still you never check if `realloc` returned `NULL`. – Iharob Al Asimi Feb 03 '15 at 18:26
  • now I checked for it, but it didn't help, the program crashes on reallocation line and does not advance to return value checking, maybe I did something wrong on reallocating – sasha199568 Feb 03 '15 at 18:32
  • Also, remove the casts from `malloc`/`realloc` it wont fix your program but it will make it more readable. – Iharob Al Asimi Feb 03 '15 at 18:40
  • You are using `path` and `paths` and allocate memory for the pointers these represent, but never allocate memory (space) for data to be written. (i.e. something like `for(i=0;i – ryyker Feb 03 '15 at 18:42
  • I did something like this just before // path initialization, I guess it works, because latter I print all the paths by calling print_path(paths[i], npath); – sasha199568 Feb 03 '15 at 18:58

2 Answers2

1

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;
}
Community
  • 1
  • 1
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • thank you for your code, but I do create space and with realloc I am trying to enlarge the space. The structure of this space roughly is: first_row(cell, cell), second_row(cell, cell). And the values which are in the cells are successfully printed. And what I want to accomplish is to extend my array to something like: first_row(cell, cell, cell), second_row(cell, cell, cell). Maybe I am wrong and space is not created, but how then the ints from this space are printed? – sasha199568 Feb 03 '15 at 19:22
  • @sasha199568 - see edits in answer. You may be using the allocation functions to create memory, but for pointers only, not for data. – ryyker Feb 03 '15 at 20:48
  • Thank you for your help. I decided to implement it without reallocating memory (noticed that the exact amount of memory is known after the number of operations is known). In my next attempt I tried to do malloc and understood that how I used malloc was wrong, I really have to allocate memory for every element of the array. But I still don't get how the values are printed in the code I posted... – sasha199568 Feb 05 '15 at 20:28
  • @sasha199568 - regarding _But I still don't get how the values are printed in the code I posted_, sometimes you can access areas of memory that you do not own, sometimes you cannot. I suspect if you were able to print elements of an array, without first owning them (through memory allocation, or declaration) then you invoked ***[undefined behavior](http://en.wikipedia.org/wiki/Undefined_behavior)***, a thing to avoid. In this case, the C standard has not defined (specified) any rules for a piece of code accessing memory it does not explicitly own. Sometimes it works, sometimes it does not. – ryyker Feb 05 '15 at 22:02
0

The realloc() does not fail. What fails is that you haven't allocated memory for the new pointers between paths[previous_npaths] and paths[new_npaths-1], before writing to these arrays in the loop for (j = 0; j < npaths; ++j).

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • @ryyker beat me to spot the flaw ;-) – Weather Vane Feb 03 '15 at 18:51
  • next time I am going to comment my programs really well. I believe I write to created locations, because even if I created new array between paths[previous_npaths] and paths[new_npaths-1](but I am doing it after the fail loop), in the loop which fails I start to reallocate memory from the first array, which does exist (it prints out). And the program puts the string "trying to allocate", but it does not put "reallocated", so it fails on writing to the very first array (it contains ints 1 and 2, and they are printed) – sasha199568 Feb 03 '15 at 19:32
  • Saying you "believe you write to created locations" does not make it so. To reinforce my point (and @ryyker's) I put in a cue that your program lacks, after the *second* `realloc()` to determine that it works. It was then I noticed the flaw in `for (j = 0; j < npaths; ++j) paths[j][npath-1] = paths[j][npath-2] + paths[j][j];` which breaks when `j >= old_npaths`. – Weather Vane Feb 03 '15 at 19:54