我正在实施分而治之的多项式算法,因此我可以将其与OpenCL实现进行基准测试,但我无法使malloc
工作。当我运行程序时,它会分配一堆东西,检查一些东西,然后将size/2
发送给算法。然后当我再次点击malloc
行时,会吐出这个:
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)'失败。 中止
有问题的一行是:
int *mult(int size, int *a, int *b) {
int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2;
fprintf(stdout, "size: %d\n", size);
out = (int *)malloc(sizeof(int) * size * 2);
}
我用fprintf
检查了大小,它是一个正整数(此时通常为50)。我尝试用普通号码调用malloc
,但我仍然得到错误。我只是对正在发生的事情感到困惑,到目前为止我发现的谷歌没有任何帮助。
任何想法发生了什么?我正在试图弄清楚如何编译一个更新的GCC,以防它是编译错误,但我真的很怀疑。
答案 0 :(得分:81)
99.9%的可能是你有内存损坏(缓冲区流量过大或流量不足,在释放后写入指针,在同一指针上调用两次等等)。
在Valgrind下运行您的代码,以查看您的程序执行错误的位置。
答案 1 :(得分:58)
为了让您更好地了解为什么这种情况发生,我想扩展@ r-samuel-klatchko的答案。
当你致电malloc
时,真正发生的事情比给你一大块内存要复杂得多。在引擎盖下,malloc
还会保存一些关于它给你的内存(最重要的是它的大小)的内务处理信息,这样当你调用free
时,就会知道要释放多少内存。此信息通常保存在malloc
返回给您的内存位置之前。可以找到更详尽的信息on the internet™,但(非常)基本的想法是这样的:
+------+-------------------------------------------------+
+ size | malloc'd memory +
+------+-------------------------------------------------+
^-- location in pointer returned by malloc
在此基础上(并大大简化了事情),当您调用malloc
时,它需要获得指向可用内存的下一部分的指针。一个非常简单的方法是查看它给出的前一位内存,并将size
字节进一步向下(或向上)移动到内存中。通过此实现,在分配p1
,p2
和p3
之后,您最终会看到类似内容:
+------+----------------+------+--------------------+------+----------+
+ size | | size | | size | +
+------+----------------+------+--------------------+------+----------+
^- p1 ^- p2 ^- p3
那么,是什么导致了您的错误?
好吧,想象一下你的代码错误地写了你已分配的内存量(因为你分配的内存少于你需要的问题,或者因为你在你的某个地方使用了错误的边界条件码)。假设您的代码将大量数据写入p2
,它会开始覆盖p3
的{{1}}字段中的内容。当您现在接下来调用size
时,它将查看它返回的最后一个内存位置,查看其大小字段,移至malloc
然后从那里开始分配内存。但是,由于您的代码已被覆盖p3 + size
,因此该内存位置不再位于先前分配的内存之后。
毋庸置疑,这可能会造成严重破坏!因此,size
的实现者已经输入了许多"断言"或检查,如果它们即将发生,它们会尝试进行一系列健全性检查以捕获这个(以及其他问题) 。在您的特定情况下,这些断言被违反,因此malloc
中止,告诉您您的代码即将执行它应该做的事情。
如前所述,这是一个粗略的过度简化,但足以说明这一点。 malloc
的glibc实现超过5k行,并且已经有大量关于如何构建良好的动态内存分配机制的研究,因此无法在SO答案中覆盖它。希望这能让您对实际导致问题的原因有所了解!
答案 2 :(得分:6)
我使用Valgrind的替代解决方案:
我很高兴,因为我只是帮助我的朋友调试了程序。他的程序遇到了这个确切的问题(malloc()
导致中止),并且来自GDB的错误消息也相同。
gcc -Wall -g3 -fsanitize=address -o new new.c
^^^^^^^^^^^^^^^^^^
然后运行gdb new
。当程序因随后的SIGABRT
中的malloc()
终止时,将打印出许多有用的信息:
=================================================================
==407==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000000b4 at pc 0x7ffffe49ed1a bp 0x7ffffffedc20 sp 0x7ffffffed3c8
WRITE of size 104 at 0x6060000000b4 thread T0
#0 0x7ffffe49ed19 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5ed19)
#1 0x8001dab in CreatHT2 /home/wsl/Desktop/hash/new.c:59
#2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
#3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#4 0x8001679 in _start (/mnt/d/Desktop/hash/new+0x1679)
0x6060000000b4 is located 0 bytes to the right of 52-byte region [0x606000000080,0x6060000000b4)
allocated by thread T0 here:
#0 0x7ffffe51eb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
#1 0x8001d56 in CreatHT2 /home/wsl/Desktop/hash/new.c:55
#2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
#3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
让我们看一下输出,尤其是堆栈跟踪:
第一部分说new.c:59
处有无效的写操作。该行显示为
memset(len,0,sizeof(int*)*p);
^^^^^^^^^^^^
第二部分说发生错误写入的内存是在new.c:55
处创建的。该行显示为
if(!(len=(int*)malloc(sizeof(int)*p))){
^^^^^^^^^^^
就是这样。我只花了不到半分钟的时间就找到了困扰我朋友几个小时的错误。他设法找到了故障,但是随后的malloc()
调用失败了,而无法在以前的代码中发现此错误。
总结:尝试使用-fsanitize=address
的GCC或Clang。在调试内存问题时,它会非常有用。
答案 3 :(得分:2)
你可能在某处超出分配的内存超出范围。 然后在你调用malloc
之前,底层的sw不会接收它可能有一个被malloc捕获的警卫值被破坏。
编辑...为边界检查帮助添加了这个
http://www.lrde.epita.fr/~akim/ccmp/doc/bounds-checking.html
答案 4 :(得分:2)
我收到了以下消息,类似于您的消息:
program: malloc.c:2372: sysmalloc: Assertion `(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)' failed.
在使用malloc之前,错误地调用了一些方法。错误地覆盖了乘法符号' *'使用' +',在sizeof() - 运算符之后更新因子时将字段添加到unsigned char数组。
以下是我的案例中负责错误的代码:
UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5); b[INTBITS]=(some calculation); b[BUFSPC]=(some calculation); b[BUFOVR]=(some calculation); b[BUFMEM]=(some calculation); b[MATCHBITS]=(some calculation);
在后来的另一种方法中,我再次使用了malloc,它产生了上面显示的错误信息。电话很简单(
)UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50);
在第一次调用时使用' +' -sign,这会导致错误演算并结合立即初始化数组(覆盖未分配给数组的内存) ),给malloc的内存映射带来了一些困惑。因此第二次调用出错了。
答案 5 :(得分:1)
我们得到了这个错误,因为我们忘了乘以sizeof(int)。请注意,malloc(..)的参数是一些字节,而不是机器字的数量或其他。
答案 6 :(得分:0)
我将一个应用程序从Visual C移植到Linux上的gcc,我遇到了与
相同的问题malloc.c:3096:sYSMALLOc:在UBUNTU 11上使用gcc断言。
我将相同的代码移到了Suse发行版(在其他计算机上),我没有任何问题。
我怀疑问题不在我们的程序中,而在于自己的libc。
答案 7 :(得分:0)
我遇到了同样的问题,我在循环中使用了malloc over n,以添加新的char *字符串数据。我遇到了同样的问题,但在释放分配的内存void free()
之后问题被排序了