Repeated realloc causes crash in glibc

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Bold Gambit
    New Member
    • Jul 2010
    • 2

    #1

    Repeated realloc causes crash in glibc

    Here is the code snippet, realloc succeeds once but fails the next time. I use gcc 4.1.2, glibc 2.5.

    Code:
    typedef struct array
    {
      double *x, *y;
      size_t nelem, size;
    } array_t;
    
    #define INIT_A_SIZE 1
    int init_a(array_t *a)
    {
      if (a) {
        a->x = (double *)malloc(INIT_A_SIZE*sizeof(double));
        a->y = (double *)malloc(INIT_A_SIZE*sizeof(double));
        if (!a->x || !a->y) {
          /* technically I should free x here is y fails
             but that's not the issue */
          return -1;
        }
        a->nelem = 0;
        a->size = INIT_A_SIZE;
      }
      return 0;
    }
    
    int add_a(array_t *a, double x, double y)
    {
      if (a->nelem == a->size) {
        size_t newsize;
        double *newx, *newy;
        newsize = 2*a->size;
        newx = realloc(a->x, newsize);
        if (!newx) {
          return -2;
        }
        newy = realloc(a->y, newsize);
        if (!newy) {
          a->x = realloc(a->x, a->size);
          return -3;
        }
        a->size = newsize;
        a->x = newx;
        a->y = newy;
      }
      a->x[a->nelem] = x;
      a->y[a->nelem] = y;  
      a->nelem++;
      return 0;
    }


    This has come up before, and I went through the threads, but (as far as I can tell) my situation is different than any previous posters, because unlike their code, this code:
    1. assigns reallocated pointer to original (a->x = newx)
    2. does not free anything
    3. checks if newx or newy are NULL
    Last edited by Banfa; Jul 16 '10, 11:16 PM. Reason: Added [code] ... [/code] tags corrected code
  • Bold Gambit
    New Member
    • Jul 2010
    • 2

    #2
    Originally posted by Bold Gambit
    Here is the code snippet, realloc succeeds once but fails the next time. I use gcc 4.1.2, glibc 2.5.

    typedef struct array
    {
    double *x, *y;
    size_t nelem, size;
    } array_t;

    #define INIT_A_SIZE 1
    int init_a(array_t *a)
    {
    if (a) {
    a->x = (double *)malloc(INIT_A _SIZE*sizeof(do uble));
    a->y = (double *)malloc(INIT_A _SIZE*sizeof(do uble));
    if (!a->x || !a->y) {
    /* technically I should free x here is y fails
    but that's not the issue */
    return -1;
    }
    a->nelem = 0;
    a->size = INIT_A_SIZE;
    }
    return 0;
    }

    int add_a(array_t *a, double x, double y)
    {
    if (a->nelem == a->size) {
    size_t newsize;
    double *newx, *newy;
    newsize = 2*a->size;
    newx = realloc(a->x, newsize);
    if (!newx) {
    return -2;
    }
    newy = realloc(a->y, newsize);
    if (!newy) {
    a->x = realloc(a->x, a->size);
    return -3;
    }
    a->size = newsize;
    a->x = newx;
    a->y = newy;
    a->nelem++;
    }
    a->x[a->nelem] = x;
    a->y[a->nelem] = y;
    return 0;
    }



    This has come up before, and I went through the threads, but (as far as I can tell) my situation is different than any previous posters, because unlike their code, this code:
    1. assigns reallocated pointer to original (a->x = newx)
    2. does not free anything
    3. checks if newx or newy are NULL
    Mistake in cut-and-paste, but not in original code: Move a->nelem++ down after a->y[a->nelem] = y;
    Sorry about that.

    Comment

    • Banfa
      Recognized Expert Expert
      • Feb 2006
      • 9067

      #3
      OK to start will you have made this more complex than required by not coding the relationship between the data into the program.

      That is there is a direct correlation between x and y in you array structure, they always have the same number of elements. Therefore they should not be separate arrays, create a type to embody this relationship and then create an array of that type like so

      Code:
      typedef struct data
      {
        double x;
        double y;
      } data_t;
      
      typedef struct array
      {
        data_t *data;
        size_t nelem, size;
      } array_t;
      You halve the number of mallocs/reallocs and you do not have to handle allocation of y failing when x has already been allocated. Generally the code becomes less complex and that means more maintainable.

      I can't see anything particularly wrong with the but I am just trying it.

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        Line 36 is wrong, byt this time a->x is not valid you need to reallocate from newx

        Line 30 and 34 you are allocating the number of elements but not factoring in the size of the data type (double).

        Comment

        Working...