user2252004
user2252004

Reputation: 49

C segfaults when allocating memory that has been freed

I am working on a program that uses a circular buffer to store stock quotes. The buffer has to be able to expand and shrink depending on whether or not certain conditions are met during each update of the buffer. However, I am having an issue where I can expand the buffer once, but after that if I try to expand it again I get segfaults. I am using a new buffer and assigning it to the old one after freeing the memory that the old buffer was using. My code is as follows.

cbuf* cbuf_init(){

    cbuf *buffer = malloc(sizeof(cbuf) + 9 * sizeof(quote));
    buffer->currSize = 0;
    buffer->maxSize = startSize;
    buffer->start = 0;
    buffer->end = 0;
    buffer->freeSlots = startSize;
    return buffer;
}


void cbuf_update(cbuf *cb_ptr, unsigned int time, double rate){
    int threeFourths;    
    threeFourths = (3 * cb_ptr->maxSize)/4;


    if(cb_ptr->freeSlots == 0){
        printf("\n\nEXPANDING CIRCULAR BUFFER!\n\n");

        int newSize;
        newSize = (cb_ptr->maxSize * 2) - 1;
        printf("Newsize: %d\n", newSize);
        cbuf *newBuffer = malloc(sizeof(cbuf) + newSize * sizeof(quote));
        printf("pastthe malloc\n");
        newBuffer->maxSize = cb_ptr->maxSize * 2;
        newBuffer->start = cb_ptr->start;
        newBuffer->end = cb_ptr->end;
        newBuffer->freeSlots = newBuffer->maxSize - cb_ptr->maxSize;

        int x;
        int counter;
        counter = 0;

        for(x = cb_ptr->end; x < cb_ptr->maxSize; x ++){
            newBuffer->quoteBuffer[counter].time = cb_ptr->quoteBuffer[x].time;
            newBuffer->quoteBuffer[counter].rate = cb_ptr->quoteBuffer[x].rate;
            counter ++;
        }
        int y;
        for(y = 0; y < cb_ptr->start; y ++){
            newBuffer->quoteBuffer[counter].time = cb_ptr->quoteBuffer[y].time;
            newBuffer->quoteBuffer[counter].rate = cb_ptr->quoteBuffer[y].rate;
            counter++;
        }
        newBuffer->start = cb_ptr->maxSize;
        newBuffer->end = 0;
        printf("newBuffer start: %d\n", newBuffer->start);
        free(cb_ptr);
        *cb_ptr = *newBuffer;


    }   



}

and my main is:

int main(){

    cbuf *cb1 ;
    cb1 = cbuf_init() ;
    cbuf_update(cb1, 60, 1.291) ;
    cbuf_update(cb1, 63, 1.287) ;
    cbuf_update(cb1, 63, 1.231) ;
    cbuf_update(cb1, 69, 1.229) ;
    cbuf_update(cb1, 72, 1.247) ;
    cbuf_update(cb1,361,1.291);
    cbuf_update(cb1, 411, 1.291) ;
    cbuf_update(cb1, 412, 1.281) ;
    cbuf_update(cb1, 413, 1.292) ;
    cbuf_update(cb1, 414, 1.284) ;
    cbuf_update(cb1, 414, 1.290) ;
    cbuf_update(cb1, 511, 1.241) ;
    cbuf_update(cb1, 512, 1.251) ;
    cbuf_update(cb1, 513, 1.232) ;
    cbuf_update(cb1, 514, 1.202) ;
    cbuf_update(cb1, 517, 1.119) ;
    cbuf_update(cb1, 551, 1.080) ;
    cbuf_update(cb1, 552, 1.081) ;
    cbuf_update(cb1, 553, 1.079) ;
    cbuf_update(cb1, 554, 1.088) ;
    cbuf_update(cb1, 561, 1.072) ;
    cbuf_update(cb1, 562, 1.113) ;
    cbuf_update(cb1, 563, 1.091) ;
    cbuf_update(cb1, 564, 1.092) ;
    cbuf_update(cb1, 571, 1.089) ;
    cbuf_update(cb1, 572, 1.073) ;
    cbuf_update(cb1, 573, 1.061) ;
    cbuf_update(cb1, 574, 1.111) ;
    cbuf_update(cb1, 581, 1.119) ;
    cbuf_update(cb1, 582, 1.123) ;
    cbuf_update(cb1, 583, 1.151) ;
    cbuf_update(cb1, 584, 1.153) ;  
    cbuf_dump(cb1);
    return 0;

}

cbuf_dump simply prints out the information pertaining to the buffer. When using this code, I get the following output:

EXPANDING CIRCULAR BUFFER!

Newsize: 19
pastthe malloc
newBuffer start: 10


EXPANDING CIRCULAR BUFFER!

Newsize: 39
Segmentation fault (core dumped)

As you can see, I inserted print statements so that during runtime I could see where the code was right before it segfaulted. It is able to expand the first time, but when it tries to allocated memory a second time for a new "newBuffer", it segfaults.

Any ideas?

Upvotes: 0

Views: 203

Answers (1)

Valeri Atamaniouk
Valeri Atamaniouk

Reputation: 5163

This line:

*cb_ptr = *newBuffer;

clearly does something you don't want. You probably meant:

cb_ptr = newBuffer;

If your cb_ptr parameter is in/out, then it should be used as:

void cbuf_update(cbuf **cb_ptr, unsigned int time, double rate)
...
if((*cb_ptr)->freeSlots == 0){
...
    *cb_ptr = newBuffer;
...

And in main:

cbuf_update(&cb1, 60, 1.291) ;

Upvotes: 1

Related Questions