#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    5
    Rep Power
    0

    Dynamic int array, realloc problem


    I have the following dynamic array that is initialised at 3 and reinitialised each time is filled.
    I do not know why it is working from 1 to 5 and not after five.

    What I'm doing wrong?

    The function insert(int * , int), puts a new integer value into the array.
    The function getLength(int *) counts the number of elements from the array, with the condition that it will stop if it gets a zero value.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    enum {FALSE, TRUE};
    #define INITIAL 3
    
    int insert(int * , int);
    int getLength(int *);
    
    int main(){
        int * tab;
    
        //initialisation
        tab =  (int *) malloc(sizeof(int) * INITIAL);
        if (!tab)
            return 1;
        tab[0]=0;
    
        int i,j, status;
    
        for(i = 1; i < 8; i++){
            status = insert(tab, i);
            if(status == TRUE){
                printf("newVal=%d tabLength=%d tab={", i, getLength(tab));
                for(j = 0; j < getLength(tab); j++)
                    printf("%d,", tab[j]);
                printf("}\n");
            }
            else
                printf("Insert error %d\n", i);
        }
    
        return 0;
    }
    
    int insert(int *tab, int val){
        int len = getLength(tab);
    
        if (len % INITIAL == (INITIAL - 1)){
            tab = realloc(tab, INITIAL * sizeof(int));
            if (tab == NULL)
                return FALSE;
        }
    
        tab[len] = val;
        tab[len+1] = 0;
    
        return TRUE;
    }
    
    int getLength(int * tab){
        int i,elem=0;
    
        for(i=0; tab[i] !=0 ; i++)
            elem++;
    
        return elem;
    }
    that prints :
    Code:
    newVal=1 tabLength=1 tab={1,}
    newVal=2 tabLength=2 tab={1,2,}
    newVal=3 tabLength=3 tab={1,2,3,}
    newVal=4 tabLength=4 tab={1,2,3,4,}
    newVal=5 tabLength=5 tab={1,2,3,4,5,}
    newVal=6 tabLength=6 tab={1,2,3,4,5,6,1450650678,909129014,1647062068,1735288140
    ,909994100,1650553888,31549,}
    newVal=7 tabLength=14 tab={1,2,3,4,5,6,1450650678,909129014,1647062068,173528814
    0,826108020,1635000372,8076642,7,}
    
    Process returned 0 (0x0)   execution time : 0.042 s
    Press any key to continue.
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,955
    Rep Power
    481
    Your reallocations are always the same size.
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    5
    Rep Power
    0
    Yes, I thought it should be like that.
    Now, I changed it for the new complete size:
    Code:
           tab = realloc(tab, (len + INITIAL) * sizeof(int));
    and I get :
    Code:
    newVal=1 tabLength=1 tab={1,}
    newVal=2 tabLength=2 tab={1,2,}
    newVal=3 tabLength=2 tab={10827104,10819656,}
    Insert error 4
    Insert error 5
    Insert error 6
    Insert error 7
    
    Process returned 0 (0x0)   execution time : 0.025 s
    Press any key to continue.
  6. #4
  7. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,413
    Rep Power
    1871
    There are two things you're doing wrong.

    > tab = realloc(tab, (len + INITIAL) * sizeof(int));
    If realloc fails, the old memory is NOT freed. So you should use a temp pointer to test for success first.
    Eg.
    Code:
    void *temp = realloc(tab, (len + INITIAL) * sizeof(int));
    if ( temp ) {
      tab = temp;
    }
    > int insert(int *tab, int val)
    If realloc moves the block to somewhere else in memory, you need to return a modified pointer back to main.
    Say for example
    Code:
    int insert(int **tab, int val) {
        ... realloc(*tab, (len + INITIAL) * sizeof(int)); ...
        ...
        (*tab)[len] = val;
        ...
    }
    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
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    5
    Rep Power
    0
    Originally Posted by salem
    There are two things you're doing wrong.

    > tab = realloc(tab, (len + INITIAL) * sizeof(int));
    If realloc fails, the old memory is NOT freed. So you should use a temp pointer to test for success first.
    Eg.
    Code:
    void *temp = realloc(tab, (len + INITIAL) * sizeof(int));
    if ( temp ) {
      tab = temp;
    }
    I modified this and I got:
    Code:
    newVal=1 tabLength=1 tab={1,}
    newVal=2 tabLength=2 tab={1,2,}
    newVal=3 tabLength=3 tab={1,2,3,}
    newVal=4 tabLength=3 tab={11089248,11081800,3,}
    Insert error 5
    Insert error 6
    Insert error 7
    
    Process returned 0 (0x0)   execution time : 0.027 s
    Press any key to continue.
    Originally Posted by salem
    > int insert(int *tab, int val)
    If realloc moves the block to somewhere else in memory, you need to return a modified pointer back to main.
    Isn't the first modification going to do this ?

    Originally Posted by salem
    Say for example
    Code:
    int insert(int **tab, int val) {
        ... realloc(*tab, (len + INITIAL) * sizeof(int)); ...
        ...
        (*tab)[len] = val;
        ...
    }
    This I do not understand.
    I tryed changing tab form int * to int ** everywhere, but it does nothing.
    And I also do not undestend the last thing (*tab)[len] = val; (*tab) is a cast, but it is aplied to what ?
  10. #6
  11. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    5
    Rep Power
    0
    now the code is:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    enum {FALSE, TRUE};
    #define INITIAL 3
    int dimTab = 0;
    
    int insert(int *, int);
    int getLength(int *);
    
    int main(){
        int * tab;
    
        //initialisation
        tab =  (int *) malloc(sizeof(int) * INITIAL);
        if (!tab)
            return 1;
        tab[0]=0;
        dimTab += INITIAL;
    
        int i,j, status;
    
        for(i = 1; i < 8; i++){
            status = insert(tab, i);
            if(status == TRUE){
                printf("newVal=%d tabLength=%d tab={", i, getLength(tab));
                for(j = 0; j < getLength(tab); j++)
                    printf("%d,", tab[j]);
                printf("}\n");
            }
            else
                printf("Insert error %d\n", i);
        }
    
        return 0;
    }
    
    int insert(int *tab, int val){
        int len = getLength(tab);
    
        if (len == (dimTab -1) ){
            void *temp = realloc(tab, (dimTab + INITIAL) * sizeof(int));
            if ( temp ) {
                tab = temp;
                dimTab += INITIAL;
            }else
                return FALSE;
        }
    
        tab[len] = val;
        tab[len+1] = 0;
    
        return TRUE;
    }
    
    int getLength(int * tab){
        int i,elem=0;
    
        for(i=0; tab[i] !=0 ; i++)
            elem++;
    
        return elem;
    }
  12. #7
  13. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,413
    Rep Power
    1871
    Like this
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    enum {FALSE, TRUE};
    #define INITIAL 3
    
    int insert(int ** , int);
    int getLength(int *);
    
    int main(){
        int * tab;
    
        //initialisation
        tab = malloc(sizeof(int) * INITIAL);
        if (!tab)
            return 1;
        tab[0]=0;
    
        int i,j, status;
    
        for(i = 1; i < 8; i++){
            status = insert(&tab, i);
            if(status == TRUE){
                printf("newVal=%d tabLength=%d tab={", i, getLength(tab));
                for(j = 0; j < getLength(tab); j++)
                    printf("%d,", tab[j]);
                printf("}\n");
            }
            else
                printf("Insert error %d\n", i);
        }
    
        return 0;
    }
    
    int insert(int **tab, int val){
        int len = getLength(*tab);
    
        if (len % INITIAL == (INITIAL - 1)){
            void *temp = realloc(*tab, INITIAL * sizeof(int));
            if (temp == NULL)
                return FALSE;
            *tab = temp;
        }
    
        (*tab)[len] = val;
        (*tab)[len+1] = 0;
    
        return TRUE;
    }
    
    int getLength(int * tab){
        int i,elem=0;
        for(i=0; tab[i] !=0 ; i++)
            elem++;
        return elem;
    }
    
    
    
    $ gcc foo.c
    $ ./a.out 
    newVal=1 tabLength=1 tab={1,}
    newVal=2 tabLength=2 tab={1,2,}
    newVal=3 tabLength=3 tab={1,2,3,}
    newVal=4 tabLength=4 tab={1,2,3,4,}
    newVal=5 tabLength=5 tab={1,2,3,4,5,}
    newVal=6 tabLength=6 tab={1,2,3,4,5,6,}
    newVal=7 tabLength=7 tab={1,2,3,4,5,6,7,}

    Comments on this post

    • ionmang20 agrees : good advice
    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
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2013
    Posts
    5
    Rep Power
    0
    Thanks, it works.

IMN logo majestic logo threadwatch logo seochat tools logo