日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Memory Management in Open Cascade

系統(tǒng) 2215 0

Open Cascade 中的內(nèi)存管理

Memory Management in Open Cascade

eryar @ 163 . com

一、 C ++中的內(nèi)存管理 Memory Management in C ++

1. 引言

為了表現(xiàn)出多態(tài),在 C ++中就會(huì)用到大量的指針和引用。指針?biāo)傅膶?duì)象是從內(nèi)存空間中借來(lái)的,當(dāng)然要及時(shí)歸還。特別是指針在程序中隨心所欲地創(chuàng)建,因此,一個(gè)指針究竟指向哪個(gè)對(duì)象,一個(gè)對(duì)象到底被幾個(gè)指針?biāo)赶颍浅绦騿T十分關(guān)注的事情。

C ++中涉及到的內(nèi)存管理問(wèn)題可以歸結(jié)為兩方面:正確地掌握它和有效地使用它。好的程序員會(huì)理解這兩個(gè)問(wèn)題為什么要以這樣的順序列出。因?yàn)閳?zhí)行得再快、體積再小的程序,如果不按所期望的方式去執(zhí)行也是沒(méi)什么用處的程序。對(duì)于大多數(shù)程序員,正確地掌握意味著正確地調(diào)用內(nèi)存分配和釋放函數(shù);有效地使用意味著編寫自定義版本的內(nèi)存分配和釋放函數(shù)。顯然,正確地掌握它要重要些。

C 中,只要用 malloc 分配的內(nèi)存沒(méi)有用 free 釋放就會(huì)產(chǎn)生內(nèi)存泄露。在 C ++中肇事者的名字換成了 new delete ,但是問(wèn)題依然存在。當(dāng)然,有了析構(gòu)函數(shù)情況稍有改觀。因?yàn)槲鰳?gòu)函數(shù)為所有將被銷毀的對(duì)象提供了一個(gè)方便的調(diào)用 delete 的場(chǎng)所,但這同時(shí)又帶來(lái)了更多的煩惱,因?yàn)? new delete 是隱式地調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)的。而且可以在類中和類外自定義 new delete 操作符,這又帶來(lái)了復(fù)雜性,增加出錯(cuò)的機(jī)會(huì)。

2. 內(nèi)存分配方式

內(nèi)存分配有三種方式:

u 從靜態(tài)存儲(chǔ)區(qū)域分配。內(nèi)存在編譯時(shí)就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。例如全局變量、 static 變量;

u 從棧上分配。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)的局部變量的存儲(chǔ)單元都能在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí),這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配內(nèi)存容量有限;

u 從堆上分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行時(shí)用 malloc new 申請(qǐng)任意多少的內(nèi)存,程序員自己負(fù)責(zé)在用完時(shí)使用 free delete 來(lái)釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由我們決定,使用起來(lái)很靈活,但問(wèn)題也最多。

二、 Open Cascade 中的內(nèi)存管理 Memory Management in Open Cascade

在幾何建模的過(guò)程中,程序創(chuàng)建和刪除了大量的對(duì)象在動(dòng)態(tài)內(nèi)存中,也就是堆中。在這種情況下,標(biāo)準(zhǔn) C ++的內(nèi)存管理方式不是很高效,所以 Open Cascade 在包 Standard 中專門寫了個(gè)內(nèi)存管理程序( Memory Manager )來(lái)對(duì)內(nèi)存的分配與刪除進(jìn)行管理。

1. 用法 Usage

為了在 C 代碼中使用 Open Cascade 提供的內(nèi)存管理器,只需要將原來(lái)使用 malloc 的地方使用 Standard :: Allocate 來(lái)代替,原來(lái)使用 free 的地方使用 Standard :: Free 來(lái)代替。另外,原來(lái)使用 realloc 的地方使用 Standard :: Reallocate 來(lái)代替即可。

C ++中, operator new delete 都重新定義以便使用 Open Cascade 的內(nèi)存管理器。定義代碼如下所示:

        
          public
        
        
          :

  
        
        
          //
        
        
           Redefined operators new and delete ensure that handles are 

  
        
        
          //
        
        
           allocated using OCC memory manager
        
        
          void
        
        * 
        
          operator
        
        
          new
        
        (size_t,
        
          void
        
        *
        
           anAddress) 

  {

    
        
        
          return
        
        
           anAddress;

  }



  
        
        
          void
        
        * 
        
          operator
        
        
          new
        
        
          (size_t size) 

  { 

    
        
        
          return
        
        
           Standard::Allocate(size); 

  }



  
        
        
          void
        
        
          operator
        
         delete(
        
          void
        
         *
        
          anAddress, size_t ) 

  { 

    
        
        
          if
        
        
           (anAddress) Standard::Free(anAddress); 

  }
        
      
View Code

上述代碼是將 operator new delete placement new 都重新定義了,這樣的類的 new delete 都將由 Open Cascade 的內(nèi)存管理器來(lái)管理。

CDL extractor 為在其中所有類都采用這種方式來(lái)重新定義 operator new delete ,這樣 Open Cascade 所有的類(少數(shù)除外)都是使用 Open Cascade 的內(nèi)存管理器來(lái)管理。

2. 配置內(nèi)存管理器 Configuring memory manager

Open CASCADE 內(nèi)存管理器可以配置,按不同的優(yōu)化方式來(lái)分配內(nèi)存,主要還是看需要分配內(nèi)存的大小,或者不使用內(nèi)存優(yōu)化而直接使用 malloc free

配置方式為設(shè)置如下環(huán)境變量的值:

l MMGT _ OPT :若設(shè)置為 1 (默認(rèn)值也是為 1 ),內(nèi)存管理器將使用內(nèi)存優(yōu)化的方式來(lái)管理內(nèi)存;若設(shè)置為 0 ,則內(nèi)存的分配就是直接調(diào)用 C 的函數(shù) malloc free 來(lái)對(duì)內(nèi)存進(jìn)行管理,此時(shí),所有其它選項(xiàng)除了 MMGT _ CLEAR 外都將被忽略。若設(shè)置為 2 ,則會(huì)使用 Intel TBB 來(lái)對(duì)內(nèi)存的分配進(jìn)行優(yōu)化,此時(shí)需要有 TBB 的庫(kù)。

l MMGT _ CLEAR :若設(shè)置為 1 (默認(rèn)值也是為 1 ),分配的內(nèi)存塊將被清零;若設(shè)置為 0 ,則內(nèi)存塊將以分配時(shí)的值返回。

l MMGT _ CELLSIZE :定義了內(nèi)存池中可分配內(nèi)存塊的最大值。默認(rèn)值為 200

l MMGT _ NBPAGES :定義了頁(yè)面上可分配的小的內(nèi)存塊的數(shù)量,默認(rèn)值為 1000

l MMGT _ THRESHOLD :定義了循環(huán)利用的而不是返回給堆的內(nèi)存塊的數(shù)量,默認(rèn)值為 4000

l MMGT _ MMAP :若設(shè)置為 1 (默認(rèn)值也是為 1 ),大內(nèi)存塊的分配將會(huì)使用操作系統(tǒng)的內(nèi)存映射函數(shù)。若設(shè)置為 0 ,內(nèi)存的分配將會(huì)直接使用 malloc 直接在堆上分配。

l MMGT _ REENTRANT :若設(shè)置為 1 (默認(rèn)值為 0 ),所有調(diào)用內(nèi)存優(yōu)化的函數(shù)將會(huì)被保證安全,即使有多個(gè)不同的線程。當(dāng)在使用內(nèi)存優(yōu)化管理( MMGT _ OPT = 1 )內(nèi)存及多線程的程序時(shí),這個(gè)值需要設(shè)置為 1

注:為了使用 Open Cascade 在多線程的程序中表現(xiàn)出更好的性能,推薦如下兩種設(shè)置方式:

l MMGT _ OPT = 0

l MMGT _ OPT = 1 and MMGT _ REENTRANT = 1

3. 程序?qū)崿F(xiàn) Implementation details

Memory Management in Open Cascade

Standard _ MMgrRoot 為內(nèi)存管理器的抽象類,它定義了內(nèi)存分配的釋放的虛函數(shù)。通過(guò)環(huán)境變量 MMGT _ OPT 來(lái)選擇不同的內(nèi)存管理類,如下代碼所示:

      Standard_MMgrFactory::Standard_MMgrFactory() : myFMMgr(
      
        0
      
      
        )

{

  
      
      
        char
      
       *
      
        var
      
      
        ;

  Standard_Boolean bClear, bMMap, bReentrant;

  Standard_Integer aCellSize, aNbPages, aThreshold, bOptAlloc;



  
      
      
        //


      
        bOptAlloc   = atoi((
      
        var
      
       = getenv(
      
        "
      
      
        MMGT_OPT
      
      
        "
      
            )) ? 
      
        var
      
       : 
      
        "
      
      
        1
      
      
        "
      
      
            ); 

  bClear      
      
      = atoi((
      
        var
      
       = getenv(
      
        "
      
      
        MMGT_CLEAR
      
      
        "
      
          )) ? 
      
        var
      
       : 
      
        "
      
      
        1
      
      
        "
      
      
            );

  bMMap       
      
      = atoi((
      
        var
      
       = getenv(
      
        "
      
      
        MMGT_MMAP
      
      
        "
      
           )) ? 
      
        var
      
       : 
      
        "
      
      
        1
      
      
        "
      
      
            ); 

  aCellSize   
      
      = atoi((
      
        var
      
       = getenv(
      
        "
      
      
        MMGT_CELLSIZE
      
      
        "
      
       )) ? 
      
        var
      
       : 
      
        "
      
      
        200
      
      
        "
      
      
          ); 

  aNbPages    
      
      = atoi((
      
        var
      
       = getenv(
      
        "
      
      
        MMGT_NBPAGES
      
      
        "
      
        )) ? 
      
        var
      
       : 
      
        "
      
      
        1000
      
      
        "
      
      
         );

  aThreshold  
      
      = atoi((
      
        var
      
       = getenv(
      
        "
      
      
        MMGT_THRESHOLD
      
      
        "
      
      )) ? 
      
        var
      
       : 
      
        "
      
      
        40000
      
      
        "
      
      
        );

  bReentrant  
      
      = atoi((
      
        var
      
       = getenv(
      
        "
      
      
        MMGT_REENTRANT
      
      
        "
      
      )) ? 
      
        var
      
       : 
      
        "
      
      
        0
      
      
        "
      
      
            );

  

  
      
      
        if
      
       ( bOptAlloc == 
      
        1
      
      
         ) { 

    myFMMgr 
      
      = 
      
        new
      
      
         Standard_MMgrOpt(bClear, bMMap, aCellSize, aNbPages, aThreshold, bReentrant);



  }



  
      
      
        else
      
      
        if
      
       ( bOptAlloc == 
      
        2
      
      
         ) {

    myFMMgr 
      
      = 
      
        new
      
      
         Standard_MMgrTBBalloc(bClear);

  }

  
      
      
        else
      
      
         {

    myFMMgr 
      
      = 
      
        new
      
      
         Standard_MMgrRaw(bClear);

  }



  
      
      
        //
      
      
         Set grobal reentrant flag according to MMGT_REENTRANT environment variable
      
      
        if
      
       ( !
      
         Standard_IsReentrant )

    Standard_IsReentrant 
      
      =
      
         bReentrant;

}
      
    

當(dāng) MMGT _ OPT 設(shè)置為 1 時(shí),將會(huì)使用類 Standard _ MMgrOpt 來(lái)對(duì)內(nèi)存的分配與釋放進(jìn)行優(yōu)化。優(yōu)化方法如下:

l 小型內(nèi)存塊(小于 MMGT _ CELLSIZE 的內(nèi)存)不是單獨(dú)分配。而是分配一個(gè)大的內(nèi)存池(每個(gè)內(nèi)存池的大小是 MMGT _ NBPAGES ),每個(gè)新建內(nèi)存都被安排在當(dāng)前的內(nèi)存池中空閑的地方。若當(dāng)前內(nèi)存池被占滿,則分配另一個(gè)內(nèi)存池。在當(dāng)前的版本中,內(nèi)存池不會(huì)返回給系統(tǒng)(直到程序結(jié)束)。然而,調(diào)用函數(shù) Standard :: Free ()被釋放的內(nèi)存塊會(huì)被 free 列表記錄,以便在下一個(gè)相同大小的內(nèi)存塊分配時(shí)重新利用(循環(huán)使用)。

l 中型內(nèi)存塊(大小在 MMGT _ CELLSIZE MMGT _ THRESHOLD 之間的內(nèi)存塊)由 C 的函數(shù) malloc free 直接管理。當(dāng)這樣的內(nèi)存塊被調(diào)用函數(shù) Standard :: Free 釋放時(shí),它們也像小型內(nèi)存塊那樣被循環(huán)使用。與小型內(nèi)存塊不同的是,被釋放的 free 列表中包含的中型內(nèi)存塊可以通過(guò)函數(shù) Standard :: Purge ,使其返回到堆中。

l 大型內(nèi)存塊(大于 MMGT _ THRESHOLD 的內(nèi)存塊,包含用于管理小型內(nèi)存塊的內(nèi)存池)的分配取決于 MMGT _ MMAP 的值:若為 0 ,這些內(nèi)存塊在堆中分配;否則,將會(huì)使用操作系統(tǒng)的專用的管理內(nèi)存映射文件的函數(shù)來(lái)分配。當(dāng)使用 Standard :: Free 來(lái)釋放大型內(nèi)存塊時(shí),大型內(nèi)存塊立即返回給系統(tǒng)。

4. 利與弊 Benefits and drawbacks

Open Cascade 使用內(nèi)存管理器的最大好處就是其對(duì)小型內(nèi)存塊的循環(huán)使用機(jī)制。當(dāng)程序需要對(duì)大量小型內(nèi)存塊進(jìn)行分配與釋放時(shí),這種機(jī)制使程序速度更快。實(shí)踐表明,使用這種方式程序的性能可以提高 50 %以上。

相應(yīng)的弊端就是循環(huán)使的內(nèi)存在程序運(yùn)行時(shí)不會(huì)返回給系統(tǒng)。這就可能導(dǎo)致大量的內(nèi)存消耗,甚至可能導(dǎo)致內(nèi)存泄露。為了避免這種情況,應(yīng)該在大量使內(nèi)存的操作結(jié)束后調(diào)用函數(shù) Standard :: Purge

使用 Open Cascade 的內(nèi)存管理器( Memory Manager )導(dǎo)致的所有的內(nèi)存開銷有:

l 分配的每個(gè)內(nèi)存塊的大小都會(huì)以 8 個(gè)字節(jié)向上取整。(看其源代碼應(yīng)該是以的個(gè)字節(jié)向上取整,源程序如下所示:)

      Standard_Address Standard_MMgrRaw::Allocate(
      
        const
      
      
         Standard_Size aSize)

{

  
      
      
        //
      
      
         the size is rounded up to 4 since some OCC classes

  
      
      
        //
      
      
         (e.g. TCollection_AsciiString) assume memory to be double word-aligned
      
      
        const
      
       Standard_Size aRoundSize = (aSize + 
      
        3
      
      ) & ~
      
        0x3
      
      
        ;

  
      
      
        //
      
      
         we use ?: operator instead of if() since it is faster :-)
      
      

  Standard_Address aPtr = ( myClear ? calloc(aRoundSize, 
      
        sizeof
      
      (
      
        char
      
      
        )) : malloc(aRoundSize) );



  
      
      
        if
      
       ( !
      
         aPtr )

    Standard_OutOfMemory::Raise(
      
      
        "
      
      
        Standard_MMgrRaw::Allocate(): malloc failed
      
      
        "
      
      
        );

  
      
      
        return
      
      
         aPtr;

}
      
    

l 額外的 4 個(gè)字節(jié)(在 64 位的操作系統(tǒng)上是 8 個(gè)字節(jié))將在每個(gè)內(nèi)存塊的開始部分分配,用來(lái)保存其大小(或用來(lái)保存下一個(gè)可用的內(nèi)存塊的地址),只在 MMGT _ OPT 1 時(shí)有效。

所以不管 Open Cascade 的內(nèi)存管理器以優(yōu)化方式還是標(biāo)準(zhǔn)方式來(lái)管理內(nèi)存,內(nèi)存總的消耗都將會(huì)大一些。

?

Memory Management in Open Cascade


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 临湘市| 永吉县| 新绛县| 介休市| 河北省| 重庆市| 历史| 马边| 雷山县| 水富县| 乐昌市| 新乡县| 丹寨县| 溧水县| 吉木萨尔县| 内乡县| 邳州市| 留坝县| 东台市| 抚宁县| 天峨县| 唐海县| 宜城市| 邢台县| 大庆市| 济宁市| 商洛市| 松潘县| 景德镇市| 宜兰县| 彰化县| 长治市| 大埔县| 金阳县| 衡东县| 大连市| 论坛| 准格尔旗| 土默特左旗| 甘南县| 通辽市|