zoukankan      html  css  js  c++  java
  • Blender内存管理库(bf_intern_guardedalloc)

    Blender内部定义了自己内存泄漏检测机制,同时提供了了二套实现机制,函数整合于于bf_intern_guardedalloc库中:

    mallocn_lockfree_impl.c和mallocn_guarded_impl.c分别实现了这二套内存分配机制,头文件定义于MEM_guardedalloc.h中,为方便实现二种机制的切换,函数头使用的是函数指针方式,以便于动态切换。

    mallocn_lockfree_impl.c中的实现用于正常工作模式,mallocn_guarded_impl.c的实现用于调试模式,提供更多信息,更方便定位内存问题。

    mallocn.c中实现函数指针被赋值,默认使用mallocn_lockfree_impl.c中的函数,如果需要使用mallocn_guarded_impl.c中的函数,只需要调用MEM_use_guarded_allocator函数,实现二套机制的切换。

    在blender主程序文件中createor.c中,只有当明确指明调试模式时使用guarded模式内存分配,以方便理准确定位内存问题

     1 /* NOTE: Special exception for guarded allocator type switch:
     2    *       we need to perform switch from lock-free to fully
     3    *       guarded allocator before any allocation happened.
     4    */
     5   {
     6     int i;
     7     for (i = 0; i < argc; i++) {
     8       if (STR_ELEM(argv[i], "-d", "--debug", "--debug-memory", "--debug-all")) {
     9         printf("Switching to fully guarded memory allocator.
    ");
    10         MEM_use_guarded_allocator();
    11         break;
    12       }
    13       else if (STREQ(argv[i], "--")) {
    14         break;
    15       }
    16     }
    17     MEM_initialize_memleak_detection();
    18   }

     同时在第17行调用MEM_initialize_memleak_detection()函数实例化MemLeakPrinter(leak_detector.cc中定义)类到静态变量中,用于初始内存泄漏检测。该类只定义了析构函数,因此在程序结束时自动释放时调用析构函数,实现打印内存泄漏信息。也就无需主动调用,正发布版程序中也无需处理,不用担心性能。

    例如:MEM_guardedalloc.h中定义的函数指针:extern void *(*MEM_callocN)(size_t len, const char *str) ,在mallocn.c中将它赋值

    void *(*MEM_callocN)(size_t len, const char *str) = MEM_guarded_callocN;

    MME_lockfree_callocN函数定义于mallocn_guarded_impl.c文件中,如下: 

     1 void *MEM_guarded_mallocN(size_t len, const char *str)
     2 {
     3   MemHead *memh;
     4 
     5   len = SIZET_ALIGN_4(len);
     6 
     7   memh = (MemHead *)malloc(len + sizeof(MemHead) + sizeof(MemTail));
     8 
     9   if (LIKELY(memh)) {
    10     make_memhead_header(memh, len, str);
    11     if (UNLIKELY(malloc_debug_memset && len)) {
    12       memset(memh + 1, 255, len);
    13     }
    14 
    15 #ifdef DEBUG_MEMCOUNTER
    16     if (_mallocn_count == DEBUG_MEMCOUNTER_ERROR_VAL)
    17       memcount_raise(__func__);
    18     memh->_count = _mallocn_count++;
    19 #endif
    20     return (++memh);
    21   }
    22   print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u
    ",
    23               SIZET_ARG(len),
    24               str,
    25               (unsigned int)mem_in_use);
    26   return NULL;
    27 }

    通过代码分析可知,内存分配的保护措施就是,在请求分配内存块时,在前面额外增加了一个MemHead和MemTail,它存储了请求的内存块大小,同时更新totblock,mem_in_use,peak_mem三个与内存保护相关变量

    以下是Mem_freeN指向的函数MEM_gurded_freeN(它与Mem_allocN相对应,用于释放内存)

    
    
     1 void MEM_guarded_freeN(void *vmemh)
     2 {
     3   MemTail *memt;
     4   MemHead *memh = vmemh;
     5   const char *name;
     6 
     7   if (memh == NULL) {
     8     MemorY_ErroR("free", "attempt to free NULL pointer");
     9     /* print_error(err_stream, "%d
    ", (memh+4000)->tag1); */
    10     return;
    11   }
    12 
    13   if (sizeof(intptr_t) == 8) {
    14     if (((intptr_t)memh) & 0x7) {
    15       MemorY_ErroR("free", "attempt to free illegal pointer");
    16       return;
    17     }
    18   }
    19   else {
    20     if (((intptr_t)memh) & 0x3) {
    21       MemorY_ErroR("free", "attempt to free illegal pointer");
    22       return;
    23     }
    24   }
    25 
    26   memh--;
    27   if (memh->tag1 == MEMFREE && memh->tag2 == MEMFREE) {
    28     MemorY_ErroR(memh->name, "double free");
    29     return;
    30   }
    31 
    32   if ((memh->tag1 == MEMTAG1) && (memh->tag2 == MEMTAG2) && ((memh->len & 0x3) == 0)) {
    33     memt = (MemTail *)(((char *)memh) + sizeof(MemHead) + memh->len);
    34     if (memt->tag3 == MEMTAG3) {
    35 
    36       if (leak_detector_has_run) {
    37         MemorY_ErroR(memh->name, free_after_leak_detection_message);
    38       }
    39 
    40       memh->tag1 = MEMFREE;
    41       memh->tag2 = MEMFREE;
    42       memt->tag3 = MEMFREE;
    43       /* after tags !!! */
    44       rem_memblock(memh);
    45 
    46       return;
    47     }
    48     MemorY_ErroR(memh->name, "end corrupt");
    49     name = check_memlist(memh);
    50     if (name != NULL) {
    51       if (name != memh->name) {
    52         MemorY_ErroR(name, "is also corrupt");
    53       }
    54     }
    55   }
    56   else {
    57     mem_lock_thread();
    58     name = check_memlist(memh);
    59     mem_unlock_thread();
    60     if (name == NULL) {
    61       MemorY_ErroR("free", "pointer not in memlist");
    62     }
    63     else {
    64       MemorY_ErroR(name, "error in header");
    65     }
    66   }
    67 
    68   totblock--;
    69   /* here a DUMP should happen */
    70 }
    
    
    
    只要通过该库中函数分配的内存就能通过设置启动参数,在程序结束时显示内存泄漏等相关情况。
  • 相关阅读:
    Linux操作系统中,.zip、.tar、.tar.gz、.tar.bz2、.tar.xz、.jar、.7z等格式的压缩与解压
    R 环境内存限制的更改
    R 安装与环境配置
    开启博客园之路
    react-router @4用法整理
    react性能调谐与diff算法
    react新版本生命周期
    col-md-push-*和col-md-offset的区别
    react 基础篇 #2 create-react-app
    react-draft-wysiwyg富文本
  • 原文地址:https://www.cnblogs.com/jiaping/p/8093304.html
Copyright © 2011-2022 走看看