棘手的堆腐败Bug?

时间:2015-10-28 11:12:42

标签: c embedded heap-corruption

编辑:我认为错误纠正只不过是随机修复。我忘了正确释放堆内存。请参阅底部的实际代码和说明(我不确定是否应该编辑整个问题)。

我修复了一个错误,但不明白它导致了什么。

如果我使用帮助器指针来访问堆中列表的元素并修改其内容,那么一切都很好。但是,如果我使用返回该指针的函数直接修改元素的内容,那么在分配更多内存时,此数据会在稍后阶段被破坏。

错误仅在代码在第6个循环的循环中运行时出现。

代码不起作用

// numEvents gets corrupted after some cycles
lstEvent_NewList(&lstEvent, 1, &err); // creates a list of typeEvent in heap
//...
lstEvent_FirstNode(&lstEvent)->numEvents = events; // access first element of list directly
//...
typeCommand * p = 0;
p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
lstField_NewList(&p->lstFields, 5, &err); // THIS LINE CAUSES CORRUPTION IN numEvents

代码确实有用

typeEvent * pEvent;   // use an auxiliar to iterate through the list
lstEvent_NewList(&lstEvent, 1, &err);
//...
pEvent = lstEvent_FirstNode(&lstEvent);
pEvent->numEvents = events;
//...
typeCommand * p = 0;
p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
lstField_NewList(&p->lstFields, 5, &err); // all is good

所以,基本上如果我使用辅助来获取列表的第一个元素没有任何反应。但是,如果我使用该函数直接访问第一个元素,它会在程序中稍后中断。

结构和功能定义:

typeEvent * lstEvent_FirstNode (LSTEvent *lst)
{
    return lst->ls;
}

void lstEvent_NewList (LSTEvent * lst, uint16_t size, uint8_t * err)
{
    typeEvent* ret = 0;
    ret = (typeEvent*)malloc(sizeof(typeEvent)*size);
    if (ret == 0)
    {
        *err = E_RUN_OUT_OF_MEM;
        lst->cn = 0;
        return;
    }
    *err = 0;
    lst->ls = ret;
    lst->cn = size;
}    

void lstField_NewList (LSTField * lst, uint16_t size, uint8_t * err)
{
    typeField* ret = 0;
    ret = (typeField*)malloc(sizeof(typeField)*size);
    if (ret == 0)
    {
        *err = E_RUN_OUT_OF_MEM;
        lst->cn = 0;
        return;
    }
    *err = 0;
    lst->ls = ret;
    lst->cn = size;
}

void lstEvent_ClearList (LSTEvent * lst)
{
   free(lst->ls);
   lst->ls = 0;
   lst->cn = 0;
}    

void lstField_ClearList (LSTField * lst)
{
   free(lst->ls);
   lst->ls = 0;
   lst->cn = 0;
}

struct DM_Field{
    __packed uint8_t value;
};
typedef struct DM_Field typeField;

typedef struct LSTField {
    __packed uint16_t cn;   // Count, number of elements in array
    uint8_t * ls;           // Array  
} LSTField;

struct DM_Command{
    // some data
    LSTField lstFields;
};
typedef struct DM_Command typeCommand;

平台:STM32L1XX。

编辑:这段代码更接近现实。

代码不起作用

typeCommand * p = 0;
for (uint16_t i=0; i<1000; i++)
{
    // numEvents gets corrupted after some cycles
    lstEvent_NewList(&lstEvent, 1, &err); // creates a list of typeEvent in heap
    //...
    lstEvent_FirstNode(&lstEvent)->numEvents = events; // access first element of list directly
    //...
    p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
    lstField_NewList(&p->lstFields, 5, &err); // THIS LINE (was thought to be causing) CORRUPTION IN numEvents
    //...
    lstEvent_ClearList(&lstEvent);
    lstField_ClearList(&p->lstFields);
    p = 0;
}

代码确实有用

typeCommand * p = 0;
typeEvent * pEvent;   // use an auxiliar to iterate through the list
for (uint16_t i=0; i<1000; i++)
{
    lstEvent_NewList(&lstEvent, 1, &err);
    //...
    pEvent = lstEvent_FirstNode(&lstEvent);
    pEvent->numEvents = events;
    //...
    p = (typeCommand *) malloc(sizeof(typeCommand)); // do some more allocations
    lstField_NewList(&p->lstFields, 5, &err); // all is good
    //...
    lstEvent_ClearList(&lstEvent);
    lstField_ClearList(&p->lstFields);
    free(p);  // freeing properly now
    p = 0;
}

0 个答案:

没有答案