【问题标题】:C segfaults when allocating memory that has been freed分配已释放的内存时出现 C 段错误
【发布时间】:2013-05-17 18:10:48
【问题描述】:

我正在开发一个使用循环缓冲区来存储股票报价的程序。缓冲区必须能够根据缓冲区的每次更新期间是否满足某些条件来扩展和收缩。但是,我遇到了一个问题,我可以扩展一次缓冲区,但之后如果我尝试再次扩展它,我会遇到段错误。我正在使用一个新缓冲区,并在释放旧缓冲区正在使用的内存后将其分配给旧缓冲区。我的代码如下。

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;


    }   



}

我的主要是:

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 只是打印出与缓冲区有关的信息。使用此代码时,我得到以下输出:

EXPANDING CIRCULAR BUFFER!

Newsize: 19
pastthe malloc
newBuffer start: 10


EXPANDING CIRCULAR BUFFER!

Newsize: 39
Segmentation fault (core dumped)

如您所见,我插入了打印语句,以便在运行时我可以看到代码在发生段错误之前的正确位置。它第一次可以扩展,但是当它第二次尝试为新的“newBuffer”分配内存时,它会出现段错误。

有什么想法吗?

【问题讨论】:

  • 我们可以少一点代码吗?尝试将您的问题最小化为尽可能小的示例,然后更新您的问题。
  • 编辑为仅显示扩展缓冲区的问题
  • 您在cbuf_update 中的最后一行在我看来非常可疑。 *cb_ptr = *newBuffer 会做一些奇怪的事情。一方面,在上一行中,你释放了cb_ptr,所以给它分配一些东西是不好的。通过使用*(ptr) = *(ptr),您将对对象进行按位复制,这可能是理想的,也可能不是理想的。在我看来,您希望cbuf_update 的第一个参数是cbuf**,这样您的最后一行就可以是*cb_ptr = newBuffer。当然,所有其他对cb_ptr 的引用都必须看起来像*cb_ptr-&gt;。我不确定这是否能解决您的问题,但这是内存损坏。
  • 使用我之前评论中的每个可用角色是否可以获得奖励积分? twoosh 有一个 SO 名称吗? ;-)
  • 我知道在 cbuf_update 中将我的第一个参数更改为 cbuf** 可能会使解决此问题变得容易得多。然而,该函数的原型使用 cbuf* 并且对于该程序必须保持这种方式。基本上我正在尝试创建一个新的 cbuf,将当前的 cbuf 分配给新的 cbuf,然后释放旧 cbuf 正在使用的内存

标签: c arrays


【解决方案1】:

这一行:

*cb_ptr = *newBuffer;

显然做了一些你不想要的事情。您可能的意思是:

cb_ptr = newBuffer;

如果你的cb_ptr参数是in/out,那么它应该被用作:

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

主要是:

cbuf_update(&cb1, 60, 1.291) ;

【讨论】:

    猜你喜欢
    • 2014-04-02
    • 2016-05-08
    • 1970-01-01
    • 2019-05-21
    • 2019-05-25
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    • 2017-03-22
    相关资源
    最近更新 更多