Search code examples
csegmentation-faultrealloc

Am I getting a segmentation fault due to an incorrect realloc?


struct model
{
    char *cam;
    int *to_location, *go_location;
    int to_count, go_count;
    int length, size;
};

struct model *
initialize(int l)
{
    struct model *c;
    c = (struct model *)malloc(sizeof(struct model));
    assert(c != NULL);
    c->length = l;
    c->size = 2 * l;
    c->cam = (char *)malloc(2 * l * sizeof(char));
    assert(c->cam != NULL);
    c->to_location = (int *)malloc(l * sizeof(int));
    assert(c->to_location != NULL);
    c->go_location = (int *)malloc(l * sizeof(int));
    assert(c->go_location != NULL);
    return c;
}

void 
shuffle(struct model *current, struct model *future, int to, int g)
{
    int i1, k, d1;
    char init[100000];
    current->to_count = 0;
    current->go_count = 0;
    for (i1 = 0; i1 < g; i1++)
    {
        init[i1] = 'G';
    }
    for (i1 = g; i1 < g + to; i1++)
    {
        init[i1] = 'T';
    }
    for (i1 = g + to; i1 < current->length; i1++)
    {
        init[i1] = '.';
    }
    for(i1 = 0; i1 < future->length; i1++)
    {
        d1 = rand() % current->length;
        current->cam[i1] = init[d1];
        if (current->cam[i1] == 'T')
        {
            current->to_location[current->to_count] = i1;
            current->to_count = current->to_count + 1;
        }
        if (current->cam[i1] == 'G')
        {
            current->go_location[current->go_count] = i1;
            current->go_count = current->go_count + 1;
        }
        for (k = d1; k < current->length; k++)
        {
            init[k] = init[k + 1];
        }
        current->length = current->length - 1;
    }
    current->length = future->length;
}

void 
display(struct model *current)
{
    int i;
    printf("\n<");
    current->to_count = 0;
    current->go_count = 0;
    for(i = 0; i < current->length; i++) 
    {
        if (current->cam[i] == 'T')
        {
            current->to_location[current->to_count] = i;
            current->to_count = current->to_count + 1;
        }
        else if (current->cam[i] == 'G')
        {
            current->go_location[current->go_count] = i;
            current->go_count = current->go_count + 1;
        }
        printf("%c", current->cam[i]);
    }
    printf(">\n");
    printf("\nThe total number of to's are %d, and the total number of gos      are %d. The length is %d\n", current->to_count, current->go_count, current->length);
}

void 
insert(struct model *current, struct model *future)
{
    int j, k;
    k = rand() % (current->length + 1);
    current->length = current->length + 1;
    for (j = current->length; j > k; j--)
    {
        future->cam[j] = future->cam[j - 1];
    }
    future->cam[k] = 'T';
    future->size = 2 * current->length;
    future->cam = (char *)realloc(future->cam, future->size * sizeof(char));
    assert(future->cam != NULL);
    current->size = 2 * current->length;
    current->cam = (char *)realloc(current->cam, current->size * sizeof(char));
    assert(current->cam != NULL);
}

int 
main()
{
    int l, to, go, i, k1, k2, j;
    l = 100; //l,go,to are positive
    go = 20;
    to = 20; //go+to cannot be greater than l
    struct model *current = initialize(l), *future = initialize(l);
    shuffle(current, future, to, go);
    display(current);
    for (i = 0; i < 500; i++)
    {
        for (j = 0; j < current->length; j++)
        {
            future->cam[j] = current->cam[j];
        }
        insert(current, future);
        for (j = 0; j < current->length; j++)
        {
            current->cam[j] = future->cam[j];
        }
        display(current);
    }
    return 0;
}

I am not able to find out the reason for a segmentation fault. I checked to see if I had implemented realloc correctly but from what I can tell there might not be a mistake there. the segmentation fault occurs after current->length reaches 281, so reallocation may be occurring uptill there as the initial size is 200 but why does it stop after that?


Solution

  • In initialize() you:

    c->cam = (char *)malloc(2 * l * sizeof(char));
    assert(c->cam != NULL);
    c->to_location = (int *)malloc(l * sizeof(int));
    assert(c->to_location != NULL);
    c->go_location = (int *)malloc(l * sizeof(int));
    assert(c->go_location != NULL);
    

    And then in insert() you:

    current->length = current->length + 1;
    ....
    future->size = 2 * current->length;
    future->cam = (char *)realloc(future->cam, future->size * sizeof(char));
    assert(future->cam != NULL);
    current->size = 2 * current->length;
    current->cam = (char *)realloc(current->cam, current->size * sizeof(char));
    

    And then in display() you:

    current->to_count = 0;
    current->go_count = 0;
    for(i = 0; i < current->length; i++)
    ...
            current->to_location[current->to_count] = i;
            current->to_count = current->to_count + 1;
    ...
            current->go_location[current->go_count] = i;
            current->go_count = current->go_count + 1;
    

    A similar thing also happens in shuffle()

    So you write to to to_location from 0 up to current->length and current->length continues getting bigger because of insert() and yet to_location does NOT get bigger so as soon as current->length is increased you write past the end of the to_location array and clobber something important - eventually killing the program.