Thread: How to Realloc 2-D array

  1. #1
    Registered User
    Join Date
    Apr 2006
    Posts
    10

    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
    Last edited by wots_guge; 04-13-2006 at 02:55 PM.

  2. #2
    Registered User
    Join Date
    Nov 2005
    Posts
    95

    You are messing

    I commented out your errors.

    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. #3
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    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.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  4. #4
    Registered User
    Join Date
    Apr 2006
    Posts
    10

    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;
    
    
    }
    Last edited by wots_guge; 04-13-2006 at 05:01 PM.

  5. #5
    Registered User
    Join Date
    Jun 2004
    Posts
    277
    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. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    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.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User
    Join Date
    Jun 2004
    Posts
    277
    Quote 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. #8
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Quote 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.)
    Last edited by Cactus_Hugger; 04-13-2006 at 11:28 PM.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  9. #9
    Registered User
    Join Date
    Apr 2006
    Posts
    10
    Quote 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. #10
    Registered User
    Join Date
    Apr 2006
    Posts
    10
    Quote 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. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > 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".
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    Apr 2006
    Posts
    10
    Quote 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. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    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
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. 1-D array
    By jack999 in forum C++ Programming
    Replies: 24
    Last Post: 05-12-2006, 07:01 PM
  2. 2d array question
    By gmanUK in forum C Programming
    Replies: 2
    Last Post: 04-21-2006, 12:20 PM
  3. Template Array Class
    By hpy_gilmore8 in forum C++ Programming
    Replies: 15
    Last Post: 04-11-2004, 11:15 PM
  4. Realloc problems with sturcture array inside structure
    By daveyand in forum C Programming
    Replies: 2
    Last Post: 03-29-2004, 06:48 AM
  5. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM