我的功能如下:
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也没有显示任何错误。可能是什么问题?
答案 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
的作者使用了编写超复杂断言条件的相当糟糕的编程习惯。现在我们无法弄清楚哪个特定的子条件失败了。