前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >*** glibc detected *** malloc(): memory corruption

*** glibc detected *** malloc(): memory corruption

作者头像
恋喵大鲤鱼
发布2018-08-03 17:37:13
3.9K0
发布2018-08-03 17:37:13
举报
文章被收录于专栏:C/C++基础C/C++基础

以下错误,发现是由于memset越界写引起的。

代码语言:javascript
复制
*** glibc detected *** malloc(): memory corruption: 0x09eab988 ***

在Linux Server上不好模拟出来:不过若是先malloc,再越界memset,再free此内存块,然后malloc新内存块就会出现类似错误。

代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
     char *p1 = (char*)malloc(210);
     if(p1 != NULL)
     {
         printf("malloc(210) succeeded\n");
     }
     if(p1 == memset(p1,0,300))
     {
         printf("memset(p1,0,300) succeeded\n");
     }
     free(p1);
     printf("Now char *p2 = (char*)malloc(210)\n");
     char *p2 = (char*)malloc(210);
     if(p2 != NULL)
     {
         printf("memset(p2,0,210) succeeded\n");
     }
     else
     {
         printf("memset(p2,0,210) failed\n");
     }
     return 0;
}

会出现:

代码语言:javascript
复制
malloc(210) succeeded
memset(p1,0,300) succeeded
*** glibc detected *** double free or corruption (out): 0x09f0e008 ***
Abort

有一篇类似文章也介绍了该问题,参见double free

通常我们会犯的内存问题大概有以下几种: (1)内存重复释放,出现double free时,通常是由于这种情况所致。 (2)内存泄露,分配的内存忘了释放。 (3)内存越界使用,使用了不该使用的内存。 (4)使用了无效指针。 (5)空指针,对一个空指针进行操作。

对于第一种、第二种和第五种情况,就不用多说,会产生什么后果大家应该都很清楚。

第四种情况,通常是指操作已释放的对象,如: (1)已释放对象,却再次操作该指针所指对象。 (2)多线程中某一动态分配的对象同时被两个线程使用,一个线程释放了该对象,而另一线程继续对该对象进行操作。

我们重点探讨第三种情况,相对于另几种情况,这可以称得上是疑难杂症了(第四种情况也可以理解成内存越界使用)。内存越界使用,这样的错误引起的问题存在极大的不确定性,有时大,有时小,有时可能不会对程序的运行产生影响,正是这种不易重现的错误,才是最致命的,一旦出错破坏性极大。

什么原因会造成内存越界使用呢?有以下几种情况,可供参考: 例1:

代码语言:javascript
复制
        char buf[32] = {0};
        for(int i=0; i<n; i++) //n > 32
        {
            buf[i] = 'x';
        }
        ....

例2:

代码语言:javascript
复制
        char buf[32] = {0};
        string str = "this is a test sting !!!!";
        sprintf(buf, "this is a test buf!string:%s", str.c_str()); //out of buffer space
        ....

例3:

代码语言:javascript
复制
string str = "this is a test string!!!!";
char buf[16] = {0};
strcpy(buf, str.c_str()); //out of buffer space

类似的还存在隐患的函数还有:strcat,vsprintf等,同样,memcpy, memset, memmove等一些内存操作函数在使用时也一定要注意。

当这样的代码一旦运行,错误就在所难免,会带来的后果也是不确定的,通常可能会造成如下后果:

(1)破坏了堆中的内存分配信息数据,特别是动态分配的内存块的内存信息数据,因为操作系统在分配和释放内存块时需要访问该数据,一旦该数据被破坏,以下的几种情况都可能会出现。 *** glibc detected *** free(): invalid pointer: *** glibc detected *** malloc(): memory corruption: *** glibc detected *** double free or corruption (out): 0x00000000005c18a0 *** *** glibc detected *** corrupted double-linked list: 0x00000000005ab150 ***

(2)破坏了程序自己的其他对象的内存空间,这种破坏会影响程序执行的不正确性,当然也会诱发coredump,如破坏了指针数据。

(3)破坏了空闲内存块,很幸运,这样不会产生什么问题,但谁知道什么时候不幸会降临呢? 通常,代码错误被激发也是偶然的,也就是说之前你的程序一直正常,可能由于你为类增加了两个成员变量,或者改变了某一部分代码,coredump就频繁发生,而你增加的代码绝不会有任何问题,这时你就应该考虑是否是某些内存被破坏了。

排查的原则,首先是保证能重现错误,根据错误估计可能的环节,逐步裁减代码,缩小排查空间。 检查所有的内存操作函数,检查内存越界的可能。常用的内存操作函数:

代码语言:javascript
复制
sprintf snprintf
vsprintf vsnprintf
strcpy strncpy strcat 
memcpy memmove memset bcopy

如果有用到自己编写的动态库的情况,要确保动态库的编译与程序编译的环境一致。 总结的很详细,照此情形应该是memset破坏了堆的管理数据,要搞清楚具体怎么破坏的,还要跟一下glibc malloc的代码,看一下堆的管理机制。


参考文献

[1]double free

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年05月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 参考文献
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档