malloc.c:3096:SYSMALLOC:断言失败

时间:2013-09-07 13:06:57

标签: c malloc

我的功能如下:

void Insert_ldb(int t){
    struct node_ldb *temp_ldb1,*lastnode_ldb;
    temp_ldb1=root_ldb[t];
    while(temp_ldb1->next!=NULL)
        temp_ldb1=temp_ldb1->next;
    if(temp_ldb1->next==NULL){
         lastnode_ldb=malloc(sizeof(*lastnode_ldb));//error appears at this line
         temp_ldb1->next=lastnode_ldb;
    }
}

并且struct node_ldb定义为:

struct node_ldb{
    int sno;
    int *lvar;
    int *object;
    struct node_ldb *next;
};

在编译时不会出现任何错误,但在执行时会以消息终止:

  

malloc.c:3096:sYSMALLOc:断言(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)失败。   中止

奇怪的是,同一个函数在终止之前成功执行了很多次。那么错误可能发生在其他地方吗?因为即使是valgrind也没有显示任何错误。可能是什么问题?

3 个答案:

答案 0 :(得分:3)

这有点像在调用malloc()之前发生的内存管理损坏。

损坏的内存管理数据随后调用malloc()失败。

我强烈建议使用内存检查程序运行程序,例如Valgrind,直到故障再现为止。

答案 1 :(得分:1)

内存已损坏。你可能想尝试一些简单的事情。

1)在Insert_ldb中放置一个计数器。希望程序以相同的计数器值失败。如果是这样,它可以使调试更容易。

2)向malloc添加几个字节的填充,例如从8个字节开始。

3)之后初始化内容通常是个好主意    用malloc获得记忆。

#define PAD_BYTES       8

void Insert_ldv(int t)
{
    static int counter;
    struct node_ldb *temp_ldb1, *lastnode_ldb;

    counter++;
    printf("counter = %d\n", counter);

    temp_ldb1 = root_ldb[t];   
    while (temp_ldb1->next != NULL) {
        temp_ldb1 = temp_ldb1->next;
    }                               

    if (temp_ldb1->next == NULL){
        lastnode_ldb = malloc(sizeof(*lastnode_ldb) + PAD_BYTES);
        memset(lastnode_ldb, 0, sizeof(*lastnode_ldb));
        temp_ldb1->next = lastnode_ldb;
   }                                 
}

当程序没有填充失败时,您就可以在短期内找到解决方法。将PAD_BYTES增加4的倍数,直到它不会失败。正常工作时,PAD_BYTES是内存溢出的字节数。

如何设置lvar和object?我猜这个对象可能有比为它分配的内存更多的数据项,因此它会覆盖和破坏堆。

此外,什么时候内存被释放?

答案 2 :(得分:1)

这很可能表示堆损坏。

关于这个功能有一些奇怪的事情。例如,新节点的next字段未初始化。为什么? (甚至没有提到其他领域。)

同样temp_ldb1->next==NULL中的if检查看起来过多,因为前面的while周期确保此时它已为空。

P.S。 sYSMALLOc的作者使用了编写超复杂断言条件的相当糟糕的编程习惯。现在我们无法弄清楚哪个特定的子条件失败了。