博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内存调试工具Electric Fence
阅读量:7044 次
发布时间:2019-06-28

本文共 4981 字,大约阅读时间需要 16 分钟。

注:官方地址下载不了,可能不再维护了,此是一个老项目

efence中相关环境变量控制:

302     /*303      * See if the user wants to allow malloc(0).304      */305     if ( EF_ALLOW_MALLOC_0 == -1 ) {
306 if ( (string = getenv("EF_ALLOW_MALLOC_0")) != 0 )307 EF_ALLOW_MALLOC_0 = (atoi(string) != 0);308 else309 EF_ALLOW_MALLOC_0 = 0;310 }

 

 gdb的局限性:

有的时候,gbd 给出的 crash 上下文其实并不是真正发生问题的第一现场,在多线程程序设计中,这种情景会让 bug 的追查陷入误区。

electric-fence 原理如下:

  • 重写malloc、free、realloc、calloc、valloc 函数,对于C++ 应使用 extern “C”; C 使用 extern 来导出符号;以确保应用程序使用  electric-fence 的malloc等函数
  • 系 统调用malloc会多分配一个page(注意是 虚存)  然后根据是否EF_PROTECT_BELOW 设置来决定返回新分配内存区的高地址(或低地址)给user;同时,调用 mprotect((caddr_t)address, size, PROT_NONE) 来设置多分配的page页为不可访问;这样一旦程序越界便会进入不可访问区间,因此coredump。同时,EF_ALIGNMENT 也会影响到该处。
  • electric-fence  内存管理的实现基本思路为:a. 每次向操作系统申请MEMORY_CREATION_SIZE(当前为1M)字节内存,使用mmap完成; b. 存在一片内存区 用于存放 所有 slot 信息, slot 用于管理被分配的内存信息,如返回给用户的地址以及其内部实际地址、size等; c. 分配时从当前slot 中查找是否有能满足分配需求的内存区,这里注意的是每次实际分配的内存区大小比用户请求的至少要大 一个page,大致公式为:  real_size = user_size + (alignment – (user_size  % alignment )) + page_size;   若存在则拆分内存区,修改相关slot信息 d. free  内存时不会将内存交给操作系统,而是设置free或者标志PROTECTED,PROTECTED意味着该片内存不会被再次分配,由 EF_PROTECT_FREE 控制。 若设置了EF_FREE_WIPES,还会用0xbd填充用户free的区域。

electric-fence 也有如下的缺点:

  1. 每一次分配都是利用一个 semaphore 同步,没有 thread local 的分配
  2. malloc 和 free 在 slot 都是线性查找,这也造成了整体性能的落后
  3. 内存消耗大,这个是显然的,特别对于频繁的小内存分配

2,3 点都是造成整个 lib 性能较低的原因。简单说,这还是一个比较简陋的工具,如果能借鉴 tcmalloc, jemalloc 等设计可能会更好一点。

 

注意:我在hi3520下使用时有如下错误:

Program received signal SIGSEGV, Segmentation fault.[Switching to Thread 0x40ce94c0 (LWP 779)]memalign (alignment=4, userSize=56) at efence.c:498498                      && slot->internalSize >= internalSize ) {
(gdb) bt#0 memalign (alignment=4, userSize=56) at efence.c:498#1 0x0074a2d4 in malloc (size=55) at efence.c:821#2 0x4038cc60 in operator new(unsigned int) () from /lib/libstdc++.so.6#3 0x40369e68 in std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator
const&) () from /lib/libstdc++.so.6#4 0x4036a818 in std::string::_Rep::_M_clone(std::allocator
const&, unsigned int) () from /lib/libstdc++.so.6#5 0x4036b39c in std::string::reserve(unsigned int) () from /lib/libstdc++.so.6#6 0x4036b5e8 in std::string::append(char const*, unsigned int) () from /lib/libstdc++.so.6#7 0x00135c24 in Thread::trace (this=0x403ebfd8, name=0x783070 "loop", file=0x783075 "util/trace/tracer.cpp", line=505, func=0x782fa0 "run", time=1478188527) at util/trace/tracer.cpp:88#8 0x00135de0 in Tracer::trace (this=0x403b8fac, name=0x783070 "loop", file=0x783075 "util/trace/tracer.cpp", line=505, func=0x782fa0 "run", time=1478188527) at util/trace/tracer.cpp:725#9 0x0013456c in traceOut (name=0x783070 "loop", file=0x783075 "util/trace/tracer.cpp", line=505, func=0x782fa0 "run") at util/trace/if_trace.cpp:110#10 0x0013559c in Logger::run (arg=
) at util/trace/tracer.cpp:505#11 0x401e2f9c in start_thread () from /lib/libpthread.so.0#12 0x40245b58 in clone () from /lib/libc.so.0#13 0x40245b58 in clone () from /lib/libc.so.0Backtrace stopped: previous frame identical to this frame (corrupt stack?)(gdb) q 496     for ( slot = allocationList, count = slotCount ; count > 0; count-- ) {
497         if ( slot->mode == FREE 498          && slot->internalSize >= internalSize ) {
499             if ( !fullSlot 500              ||slot->internalSize < fullSlot->internalSize){
501                 fullSlot = slot; 502                 if ( slot->internalSize == internalSize                                                                                                                                                   503                  && emptySlots[0] ) 504                     break;  /* All done, */ 505             } 506         } 507         else if ( slot->mode == NOT_IN_USE ) {
508             if ( !emptySlots[0] ) 509                 emptySlots[0] = slot; 510             else if ( !emptySlots[1] ) 511                 emptySlots[1] = slot; 512             else if ( fullSlot 513              && fullSlot->internalSize == internalSize ) 514                 break;  /* All done. */ 515         } 516         slot++; 517     } extern C_LINKAGE void * malloc(size_t size) {
        void  *allocation;              if ( allocationList == 0 ) {                 pthread_mutex_init(&mutex, NULL);                 initialize();   /* This sets EF_ALIGNMENT */         }                lock();         allocation=memalign(EF_ALIGNMENT, size);         unlock();                                                                                                                                                                                                               ▸   return allocation; }

1、查看对应的错误点,发现相关变量都是正常的

2、frame 1到frame 0中的size莫名奇妙的发生了变化

3、基于这些原因,最终没有应用起来,不知道为什么?是否程序真的有越界行为导致

问题:

若出现segment fault错误,对应的pc指针是否为导致该错误的直接原因,还是这个pc指针是随机的?

答:pc仅能作为参考,segment fault应是通过signal机制实现的,具体需要进一步研究

 

转载地址:http://oszol.baihongyu.com/

你可能感兴趣的文章
AppStore应用转让流程
查看>>
php模板引擎
查看>>
.NET Core RC2/RTM 明确了时间表
查看>>
解决Eclipse Debug source not found问题
查看>>
SQL Server SQL分页查询
查看>>
第一百一十六节,JavaScript,DOM操作样式
查看>>
互联网业务场景下消息队列架构
查看>>
java 的""和null的区别
查看>>
Redis内存压缩实战
查看>>
java-Spring 管理bean例子
查看>>
解决关于ios访问相机闪退问题
查看>>
利用ST MCU内部的基准参考电压监测电源电压及其它
查看>>
MySQL 按指定字段自定义列表排序
查看>>
MySQL字段数据全部查出【只保留中文、英文、数字、空格的词表】
查看>>
svn 创建分支、切换分支 及 合并分支 操作
查看>>
[GIt] 团队工作效率分析工具gitstats
查看>>
写给新人的面向对象的基本思维
查看>>
关于分部视图(Partial View)
查看>>
DNS污染——domain name的解析被劫持了返回无效的ip
查看>>
一步一步写一个简单通用的makefile(二)
查看>>