Cybermage
Cybermage

Reputation: 3

realloc() fails after repeated calls

I'm implementing some polynomial arithmetics in C. I use a dynamic struct to store integer factors and the polynomial degree. Besides other functions I need the operation p[X]*X, so I try to implement some kind of right shift.

But after a few shifts realloc() crashes my program. In this example it's at the third call, but if I try to shift 2 and 4 times, it crashes after the second.

/* Simple polynom type with variable length and degree n-1. */
typedef struct {
    int n;
    int *factors;
} polynom_t;


polynom_t *poly_init(int n) {
    polynom_t *p_new = malloc(sizeof(polynom_t));
    p_new->n = n;
    p_new->factors = calloc(n, sizeof(int));

    return p_new;
}

void poly_clear(polynom_t *p) {
    free(p->factors);
    free(p);
    p = NULL;
}


void poly_set(polynom_t *p, int a[], int len){
    memcpy(p->factors, a, sizeof(int)*p->n);
}


void _poly_rsz(polynom_t *p, int n) {
    if (n != p->n) {
        p->n = n;

        // This realloc() seems to fail
        p->factors = realloc(p->factors, sizeof(int) * n);
    }
}


void _poly_lsr(polynom_t *p, int i) {
    _poly_rsz(p, p->n + i);
    memmove(p->factors + i, p->factors, sizeof(int)*(p->n));
    memset(p->factors, 0, sizeof(int)*i);
}


int main(int argc, char **argv) {
    polynom_t *p2 = poly_init(11);
    int a2[11] = {1, 2, 0, 2, 2, 1, 0, 2, 1, 2, 0};
    poly_set(p2, a2, 11);
    _poly_lsr(p2, 1);  // works as expected
    _poly_lsr(p2, 1);  // works as expected
    _poly_lsr(p2, 1);  // crash
    poly_clear(p2);

    return 0;
}

Upvotes: 0

Views: 888

Answers (1)

Richard J. Ross III
Richard J. Ross III

Reputation: 55533

The problem is with this block of code here:

void _poly_lsr(polynom_t *p, int i) {
    _poly_rsz(p, p->n + i);
    memmove(p->factors + i, p->factors, sizeof(int)*(p->n));  // the problem is here!
    memset(p->factors, 0, sizeof(int)*i);
}

When you resize your polynomial, you reset it's count, which means, when you are adding 1, you are overflowing the bounds of your polynomial's array by 1. To fix, simply subtract i from the memmove count:

memmove(p->factors + i, p->factors, sizeof(int)*(p->n - i));

Upvotes: 5

Related Questions