How to Realloc 2-D array

This is a discussion on How to Realloc 2-D array within the C Programming forums, part of the General Programming Boards category; Am trying to reallocate a 4x2 matrix to a 6x4 matrix. There is no memory fault but the original values ...

1. How to Realloc 2-D array

Am trying to reallocate a 4x2 matrix to a 6x4 matrix. There is no memory fault but the original values are not retained.

Can someone please tell me if am messing something:

Code:
```	int **K1,**K2;
int i,j,Col=2,Row=4;

K1 = (int **) calloc(Row,sizeof(int **));

for (i=1;i<=Row;i++)
K1[i] = (int *) calloc(Col,sizeof(int));

for(i=1;i<=Row;i++)
{
for(j=1;j<=Col;j++)
{
K1[Row][Col] = i+j;
printf("%d \t",K1[Row][Col]);
}
printf("\n");
}

if ((K2 = (int **) realloc(K1,Row+2)) == NULL)
printf("ERROR");
else
K1 = K2;

for(i=1;i<=Row;i++)
{
if ((K2[i] = (int *) realloc(K1,Col+2)) == NULL)
printf("\n\n Error...");
else
K1[i] = K2[i];
}

for(i=Row+1;i<=Row+2;i++)
K1[i] = (int *) calloc(Col+2,sizeof(int));

printf("\n");

for(i=1;i<=Row+2;i++)
{
for(j=1;j<=Col+2;j++)
{
//K1[Row][Col] = i+j;
printf("%d \t",K1[Row][Col]);
}
printf("\n");
}```
Output:
2 3
3 4
4 5
5 6

0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

2. You are messing

Code:
```int main(void)
{
int **K1,**K2;
int i,j,Col=2,Row=4;

K1 = (int **) calloc(Row, sizeof(int*) /* sizeof(int **) */ );

for (i = 0 /*i=1*/ ; i < Row /* i<=Row */;i++)
K1[i] = (int *) calloc(Col,sizeof(int));

for(i= 0 /*i=1*/ ; i < Row /* i<=Row */;i++)
for(j = 0 /*j=1*/;j < Col /*j<=Col*/;j++)
K1[i/*Row*/][j/*Col*/] = i+j+2;

for(i= 0 ; i < Row ;i++)
{
for(j = 0 ;j < Col ;j++)
printf("%d \t",K1[i][j]);
printf("\n");
}

for(i= 0 ; i < Row ;i++)
free(K1[i]);
free(K1);

getchar();
return 0;
}```
Then you can try working on enlarging the 2D-array.

3. You've got serveral errors - including memory faults.

First: Arrays in C start at 0, not 1. In your very first for() loop, i's max value is Row, or 4. You only allocated room for 4 rows however, and K1[i] = K1[Row] = K1[4] accesses the fifth item, which you never allocated memory for. (Since they start at zero, K1[0] = first row, K1[1] = second row, etc.) This happens a lot in your code.

Code:
`printf("%d \t",K1[Row][Col]);`
Why is that in a loop? Row and Col are constant in your function at that point... so that prints the same value each time. Which means you cannot be getting the output you posted, if I'm reading your code correctly.

Finally, your use of malloc / calloc / realloc. First, they all return void *s, so you do not (and should not) cast them. (Edit: Which dude543 didn't change) Your realloc's error handling also memory leaks - when realloc fails, it doesn't free the old memory. Something like:
Code:
```a_type *temp, *actual;
...
temp = realloc(actual, somesize);
if(!temp)
{
free(actual);
// continued error handling.
}
actual = temp;```
You just need to ensure that actual doesn't become a memory leak - the above example could be modified to not free() actual if it is stored somewhere else, hence the user won't loose their data. All depends on you.

4. How to Realloc 2-D array

Thnks! have changes the index from 1 to 0, but that still doesnt solve the problem..

I want to retain the 1st values in 4x2 matrix to the 6x4 matrix. Have tried a couple of things with the dummy **K2 but doest help, now the code aborts..

Will appreciate if someone let know.. thx!

Code:
```#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int **K1,**K2;
int i,j,Col=2,Row=4;

K1 = (int **) calloc(Row, sizeof(int*));

for (i = 0 ; i < Row ;i++)
K1[i] = (int *) calloc(Col,sizeof(int));

for(i= 0 ; i < Row ;i++)
for(j = 0 ;j < Col ;j++)
K1[i][j] = i+j+2;

for(i= 0 ; i < Row ;i++)
{
for(j = 0 ;j < Col ;j++)
printf("%d \t",K1[i][j]);
printf("\n");
}

if ((K2 = (int **) realloc(K1,Row+2)) == NULL)
printf("ERROR");
else
K1 = K2;

for(i=0;i<Row;i++)
{
if ((K2[i] = (int *) realloc(K1[i],Col+2)) == NULL)
printf("\n\n Error...");
else
K1[i] = K2[i];
}

for(i=Row;i<Row+2;i++)
K1[i] = (int *) calloc(Col+2,sizeof(int));

printf("\n");

for(i=0;i<Row+2;i++)
{
for(j=0;j<Col+2;j++)
{
printf("%d \t",K1[i][j]);
}
printf("\n");
}

for(i= 0 ; i < Row+2 ;i++)
{
free(K1[i]);
free(K2[i]);
}
free(K1);
free(K2);

getchar();
return 0;

}```

5. Oki code seems to work fine until you free K1 and K2, cause I think you are freeing it twice
Since
Code:
```free() frees the memory space pointed to by ptr, which must  have  been
returned by a previous call to malloc(), calloc() or realloc().  Other-
wise, or if free(ptr) has already been called before, undefined  behav-
iour occurs.  If ptr is NULL, no operation is performed.```

6. No. They're freeing the rows one at a time, then once you're done, you free the row holders. That is to say, you allocate the number of rows. Then you allocate each row's contents one chunk at a time. You free in reverse of this. Free each row's contents, then free the row pointers themselves.

Quzah.

7. Originally Posted by quzah
No. They're freeing the rows one at a time, then once you're done, you free the row holders. That is to say, you allocate the number of rows. Then you allocate each row's contents one chunk at a time. You free in reverse of this. Free each row's contents, then free the row pointers themselves.

Quzah.
yep, folks at #c on freenode pointed me this out but the code still breaks, folks there said it might be a corrupted heap, I'm googling to learn how to use valgrind right now

8. Originally Posted by quzah
No. They're freeing the rows one at a time, then once you're done, you free the row holders. That is to say, you allocate the number of rows. Then you allocate each row's contents one chunk at a time. You free in reverse of this. Free each row's contents, then free the row pointers themselves.

Quzah.
Yes and no. Yes, you're right, he does need to free one row at a time, then the row holders. (Like he's doing.) But what I think Maragato was getting at was the segments of code like:
Code:
```free(K1);
free(K2);```
And
Code:
```free(K1[i]);
free(K2[i]);```
He only ever uses K2 as a temporary holder for the result of realloc(), and then assigns it to K1 on success. Thus they point at the same data - looking at his code, K2 doesn't point to data that K1 doesn't, and thus doesn't need to be free'd.

wots_guge: Your realloc() calls need fixing: the second parameter is how much memory to allocate, but you're forgeting to multiply by the size of your type. realloc(K1[i],Col+2) should be realloc(K1[i], (Col + 2) * sizeof(int)) for example. (And be sure you check to use the right thing in the sizeof()... sizeof(int) != sizeof(int *) )
(Edit: commenting out the free's mentioned above and changing your reallocs gives me your expected output.)

9. Originally Posted by Maragato
Oki code seems to work fine until you free K1 and K2, cause I think you are freeing it twice
It should free the matrix. Even when there is no warning, errors.. the first few values stored in K2 are not retained from R1.

Here am re-allocating the pre-existing rows and expanding the columns by 2.

Code:
```for(i=0;i<Row;i++)
{
if ((K2[i] = (int *) realloc(K1[i],Col+2)) == NULL)
printf("\n\n Error...");
else
K1[i] = K2[i];```

Here am inserting more rows and column spaces.

Code:
```for(i=Row;i<Row+2;i++)
K1[i] = (int *) calloc(Col+2,sizeof(int));```
Is there a better way to tell the compiler to move the existing chunk and expand.

A workaround could be writing data to the file and re-reading, but dont want to do that

10. Originally Posted by Cactus_Hugger
wots_guge: Your realloc() calls need fixing: the second parameter is how much memory to allocate, but you're forgeting to multiply by the size of your type. realloc(K1[i],Col+2) should be realloc(K1[i], (Col + 2) * sizeof(int)) for example. (And be sure you check to use the right thing in the sizeof()... sizeof(int) != sizeof(int *) )
(Edit: commenting out the free's mentioned above and changing your reallocs gives me your expected output.)
Fantastic stuff, thanks Hugger It really kept me busy for a lot of time.. it works fine now!

11. > it works fine now!
Post it then.
This is a fairly tricky process, and my guess is that you've assigned "works" to "it's just stopped crashing".

12. Originally Posted by Salem
> it works fine now!
Post it then.
This is a fairly tricky process, and my guess is that you've assigned "works" to "it's just stopped crashing".
Yes, it "seems" to be "working as expected". From VB experience, only last dimension of a multi-dimensional array can be expanded. I guess realloc also does the same, but probably we can use combinatin of realloc and calloc to expand it in multi-dimension.

As we can see in the output, the new allocated memory space using realloc has garbage from heap, and at rows where calloc was used it is initialized to zeros.

Code:
```#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int **K1,**K2;
int i,j,Col=2,Row=4;

K1 = (int **) calloc(Row, sizeof(int*));

for (i = 0 ; i < Row ;i++)
K1[i] = (int *) calloc(Col,sizeof(int));

for(i= 0 ; i < Row ;i++)
for(j = 0 ;j < Col ;j++)
K1[i][j] = i+j+2;

for(i= 0 ; i < Row ;i++)
{
for(j = 0 ;j < Col ;j++)
printf("%d \t",K1[i][j]);
printf("\n");
}

if ((K2 = (int **) realloc (K1,(Row+2)*sizeof(int *))) == NULL)
printf("ERROR");
else
K1 = K2;

for(i=0;i<Row;i++)
{
if ((K2[i] = (int *) realloc (K1[i],(Col+2)*(sizeof(int)))) == NULL)
printf("\n\n Error...");
else
K1[i] = K2[i];
}

for(i=Row;i<Row+2;i++)
K1[i] = (int *) calloc(Col+2,sizeof(int));

printf("\n");

for(i=0;i<Row+2;i++)
{
for(j=0;j<Col+2;j++)
{
printf("%d \t",K1[i][j]);
}
printf("\n");
}

for(i= 0 ; i < Row+2 ;i++)
{
free(K1[i]);
//free(K2[i]);  Shouldnt be free'd cos they both point to same location..
}
free(K1);
//free(K2); Shouldnt be free'd cos they both point to same location..

getchar();
return 0;

}```
Output:

2 3
3 4
4 5
5 6

2 3 -842150451 -842150451
3 4 -842150451 -842150451
4 5 -842150451 -842150451
5 6 -842150451 -842150451
0 0 0 0
0 0 0 0

13. Yes, you got it wrong here.
> if ((K2[i] = (int *) realloc (K1[i],(Col+2)*(sizeof(int)))) == NULL)

Since they are the same, your effort to avoid stamping on the old pointer fails.

There is no need to have a "temp" of the same type, you can just use a void* for your temp variable. Plus being void*, there's no chance of you accidentally trying to dereference it without the compiler getting upset.

As in
Code:
```void *temp;
temp = realloc( K1[i],(Col+2)*sizeof(int) );
if ( temp != NULL ) {
K1[i] = temp;
}```
And why are you still casting the return result of malloc functions?
http://faq.cprogramming.com/cgi-bin/...&id=1043284351
If, without casts you're getting messages about assigning the result of malloc,
"cannot convert int to pointer" - means you forgot to include stdlib.h, so include it
"cannot convert void* to type*" - means you're using a C++ compiler to compile C, so switch to a C compiler.

> the new allocated memory space using realloc has garbage from heap
Correct - you need to clear the memory yourself.
There is no 'calloc' version of realloc.
In fact, using calloc can be a problem when you're trying to allocate 'initialised' pointers and/or floats (or structures containing them).
http://www.eskimo.com/~scs/c-faq.com/malloc/calloc.html