我爱电脑技术论坛's Archiver

LOK 发表于 2008-4-18 10:46

为C++标准库容器写自己的内存分配程序

根据sgi 的STL源码的二级分配算法改写的内存池分配程序,只要稍微修改就可以实现共享内存方式管理,使用C++标准库容器中的map,set,multimap,multiset测试通过,vector测试通不过,原因是在内存回收的时候考虑的比较简单,vector每次分配内存个数不固定,回收也不固定,这样的话,程序还需要继续完善。\,lb6G@Eb [%p`
F2z-ccp"s
  内存池管理程序源码如下: ^[r:MC?)j;y
l&h#A)G_
以下是引用片段: U ?x4`m}O1@
#ifndef MY_ALLOCATOR_H_
*x4}$N:ci8uY C?'X #define MY_ALLOCATOR_H_
azW2Y M\Sp.C;g#H #include "stdafx.h" :~F~~5KG R q"q6?
#include <limits> 1MNuP7Qv vS
#include <iostream>
Q8gT2R2s-?6\R9U namespace happyever  @6Ypk z8q,Su d s
{
0D Xe jy)j   enum { NODENUMS = 2 };
j5DZ"a3v7r"\s^   union _Obj  
Pg*E}~C[/v   { -zi1Blk2j N'v2J
    union _Obj* M_free_list_link; {p2oB9hL8p
    char M_client_data[1];     g+Yh$|$]7}A_
  } ; n UF:gsQ,ZW
  typedef union _Obj Obj; T4Qt#b-G(QDl:W
  struct _Cookie [BP EL&v(p
  { !Q@:B/Ez(E
    int iShmKey;        /* 共享内存键值 */
*d.JWW V9~R     int iShmID;         /* iShmKey对应的shmid */ _ Ee({f-h W
    int iSemKey;        /* 锁信号键值 */ IC4JO ?P"NV-y%W[z'e
    int iSemID;         /* 锁信号标识 */
heOY}ig&O*hi^     int iTotalsize;    /* 容器总容量 */ d-U V(Mh;fe
    void* pStartall;   /* 共享内存自身地址 */
(lw2b2h Bb0` g^N"n     char* pStartfree;  /* 自由空间的开始地址*/
!F HaEum0W @K     char* pEndfree;    /* 自由空间的结束地址*/ i3\&rb3{ a,]3R
    int iUseNum[NODENUMS]; jxC TI%Z
    /*用来存放free_list中节点的size*/ C P:X8qW3T)cVP
    short sFreelistIndex[NODENUMS];
7H!N#B;I*Kg#a|     /*存放分配内存节点的链表*/
8s_p3q'j N@8z     Obj* uFreelist[NODENUMS]; &k5H1Y};B*f ?JrY
  };
+t.s;TpA x*ri E   typedef struct _Cookie Cookie; +t9a+d+zf
  //Obj; w PUn[(g/g9{9}P
  //Cookie; +e{T8A-F/mCs _
  static Cookie *pHead = NULL; FRpn|d%\%M
  template <class T> Ym4MAB+W2C7ieq
  class MyAlloc  
a)n_ ID ?dE@ l   { /u6|lQ.D%f%c3~)r
  private: 8cv}8R2t oM h.zM
    static const int ALIGN = sizeof(Obj);
;M3hAvxk     int round_up(int bytes); 8isZ'ua)WQ+@
    int freelist_index(int bytes); A$F\6Y@c8T
    int freelist_getindex(int bytes); 8[)w _z6W_om
    char* chunk_alloc(int size, int *nobjs);
1y)s|P,V#N^;`     void* refill(int num,int n); 1| g/LN:iNi+oi EVQ
  public:
Q Lm,jN4hv     // type definitions
qO,ce(uMj3b:~'g     typedef T        value_type; /V G-EX9fZ F0^y
    typedef T*       pointer; ?QVS8_'v
    typedef const T* const_pointer;
&s(mA ?)h;P_     typedef T&       reference; (K(o x*X(i U;[
    typedef const T& const_reference; 1h f g3H-_
    typedef std::size_t    size_type; Vt6Cc'H9w#RM(^L
    typedef std::ptrdiff_t difference_type; N!XD&I8|A
    template <class U>
Q US.iR M$b(AE     struct rebind  
w:x5z.v{+w     { g7r4a-N,D&fn?
      typedef MyAlloc<U> other; %j X1Hqtn5C
    }; ?3T)P`7Y,HL
    pointer address (reference value) const  jE Q8og%L`UU
    { 9T"D,QF;Uz-I-wNb
      return &value; j'nrH%G\
    } (~i}Lb j;`
    const_pointer address (const_reference value) const  
.F0ar Vz     { slO `nmX
      return &value;
d#El?y@c"r8gh     } !LcWg(W/M's3sI x
    MyAlloc() throw()  
xZ/N3myFMTaB     { 0f p*yq9q*Sal
      std::cout<<"MyAlloc"<<std::endl; f2Ft7koI8^
    }
8x*pu!^(Rs e5^ }     MyAlloc(const MyAlloc& x) throw()  
Rn9?6p1{%snz9|     {
`jVDyj6gz5A       std::cout<<"const MyAlloc"<<std::endl; hMX,G} H:H,H|
    }
H,[AlR-f,m0G     template <class U>
Y vsmp[y.F*T8[     MyAlloc (const MyAlloc<U>& x) throw() ]KI;f'_'^'T U
    { 5i)wA'| t}
      std::cout<<"const MyAlloc<U>"<<std::endl;
2{X;Ejn'iuX1B     }
"xV%dG{b0L     ~MyAlloc() throw()  
y,RK$^`Y.[*} v v!]"z r     {
5F i#e{ j6? V[:F!R       std::cout<<"~MyAlloc"<<std::endl; ;} y$?:r2aL@v?
    } A wp,o/tz*Yp;S
    size_type max_size () const throw()  /J7}`&a$cv
    {
qO6CoF)X0z1@%[       return std::numeric_limits<std::size_t>::max() / sizeof(T); 8i%l9`B8s
    }
P)f5z5]@+Y,kd     //void PrintFreelistAndCookie(); P8G'Z ?n{9bu
    pointer allocate (size_type num, const void* = 0)  
)@b qw*j2h{     {
V)\:e7^:?!aENA(N       pointer ret = 0; "]X x d.u!\M]
      Obj** my_free_list; +a;g~5k#OP)c2x
      Obj* result;
7y`z.ptY0E U5U       int index;
(WJ+rcRb+O       // print message and allocate memory with global new
3M,Mt"^2ph1`       std::cerr << "allocate " << num << " element(s)"
"pX,S7va mT         << " of size " << sizeof(T) << std::endl;
*K'rkV2Q_%B a       index = freelist_index(sizeof(T));
$_6w4b,gm3eA3l%y$d       if(index >= NODENUMS) 7g8|}!y4I6NK
      { Z)fp |5~ `
        return NULL; NS_@M2`A3I
      } }$l ~q*B y n u
      my_free_list = pHead->uFreelist + index;
B:Ne\ }6oL%p       //Lock(semid,LOCK_NUM); +a/v-L fA9a@ b
      result = *my_free_list;
[k#Y.d3]3o3] c       if (result == 0)
6O7r$\Ah9\ln       {
*s*GxlE1a+z         ret = (pointer)refill((int)num, round_up(sizeof(T))); H s f%}(k~zk
      }
}w ] ~!E$j       else ~QXI|d
      { +`;gfe'[
        *my_free_list = result->M_free_list_link; j8F2w ?Cd v
        ret = (pointer)result; [;d9I#c vj
      }
v!l JPO0q6]       //UnLock(semid,LOCK_NUM);
,E2I/o0A5x#f       pHead->iUseNum[index] = pHead->iUseNum[index] + (int)num;
K U-\,t:@b x       if(0 == ret)
*Y0XX}$w!Q7`       { #YPn%be-Tm:~6li
        std::cerr << "alloc memory fail!" << std::endl;
s*BsCw E         exit(1);
V-KzWh5U i       } )}3M\'S%Vj
      std::cerr << " allocated at: " << (void*)ret << std::endl;
:S*PA^#XV:H       PrintFreelistAndCookie();
yMJq+Mo       return ret; zFw }/L
    }
D3U9O&oTW&}     void construct (pointer p, const T& value)  
Y-p#Nf+bpE     { akiH$Ah
      // initialize memory with placement new )}UOF"Z~/H
      new((void*)p)T(value);
UvG3sZ)p`3f#^[     } @Tp\ e$I[.Vn_.U
    void destroy (pointer p)  Vg%ovk;i nz
    { yA;p9K?[/m V-v b
      // destroy objects by calling their destructor yB9Rd1{ F5mjxtz.K
      p->~T();
(d|$@IM({     } 6fH B:b.J-o6{
    void deallocate (pointer p, size_type num)  *xE? Q k,r0FH[smp`
    {
e h6YR[/n(r b       Obj** my_free_list;
"^!K-IG6n       Obj* q ; X6EbJ vIymw F
      int index;
?mWS W       index = freelist_getindex(sizeof(T)); {&Ld8b rn
      if(index >= NODENUMS) /ywxm^'I
      {
]2P#d'I5b)i@^K8w         std::cerr << "deallocate memory fail!" << std::endl;
8]7}Om#J$i"Bx-_ e4?F         exit(1); c/u-q3J]$G?.r
      }
r8f4{#Cp       my_free_list = pHead->uFreelist + index;
7^*Z#t3k(]Rd       q = (Obj*) p; b8fZ0RQ3EkT
      //Lock(semid,LOCK_NUM);
} G7}3K7^5T       /*这个地方可能会有问题*/ `4X5GQ3F[d
      //for(int i=0 ;i<(int)num ; i++) &A P3V.IBT{
      {
&x$W2i(x1sr3lq         q->M_free_list_link = *my_free_list;
1EI.a&F+O"Smk         *my_free_list = q; .U8c [?f
      } BGE)t&t5i BG
      //UnLock(semid,LOCK_NUM);
J*Tuw*J9ISC       pHead->iUseNum[index] = pHead->iUseNum[index] - (int)num;
9s-QL xV'V u       
9up R7lE0Q1J N2n       std::cerr << "deallocate " << num << " element(s)" d;Ib([&ic9G:F
        << " of size " << sizeof(T) f*e#hDfCo
        << " at: " << (void*)p << std::endl; brn:d2|}(Po+j
      PrintFreelistAndCookie();
oH5wm2a p,^     }
#{ L] Q(c ~B   };
+s c?l*v4b'{;A'eQR   template <class T> a"?5`4hb
  int MyAlloc<T>::round_up(int bytes)
#q&gF~ UlL ^n9qo   {
'[ sQ0Gjj8n+@     int i; Pp{o,zA
    i = bytes; #ir&Rae \
    if(bytes < ALIGN)
'h4Wd~7[,g     {
3_|@!Oryw       i = ALIGN; ;_6B'Qk G]V
    }
!Y x*L0E {0Bl     std::cout<<"round_up:bytes="<<bytes<<" , return="<<i<<std::endl; j$x1X$x4wO,q
    return i;
{(KyK ZE Qs   }; q3hz Wa
  template <class T> A0Wr,C3jg)Nr(C@~
  int MyAlloc<T>::freelist_index(int bytes) )V7w?BiUY&s ^
  { y^u?6^ S]!o/q
    int i; fso6O0eZ*_ R v
    for(i=0 ; i< NODENUMS ; i++)
6n3fG#M{@     { } ?WkW
      if(pHead->sFreelistIndex[i] == bytes)
;h4N%P qi r*L]^         break;
Y:c fplg     }
&p6LRbe!W     if(i >= NODENUMS)
b A9Y/^"~P+~ U     {
|7_U6@q2p+\       for(i=0 ; i< NODENUMS ; i++)
6o_KKz\3Q0V(T(B       {
%G4U^$mO         if(pHead->sFreelistIndex[i] == 0) :Q!E2]8V1~ }
        { u|g`:v{z
          pHead->sFreelistIndex[i] = bytes; hB i&j!h
          std::cout<<"freelist_index:bytes="<<bytes<<" , return="<<i<<std::endl;
ki#{[\$v4}v-B`           return i; e [hBlIp_'X7H!PO
        }
WH)LyNsy       } $G6`wr8B7c2`
    }
]l/U R'?O.by@^oA/j     std::cout<<"freelist_index:bytes="<<bytes<<" , return="<<i<<std::endl; 0q I)Y'a^
    return i;
!ec$A},s;wq)C   }; P4rb%C#Z/x R)Q4}%b+W]
  template <class T>
'MY+`0Hspa   int MyAlloc<T>::freelist_getindex(int bytes) b*ex7Kai ~ ?
  {
c"m#Y Zp@9MR7h     int i; i!z/T| yd
    for(i=0 ; i< NODENUMS ; i++)
8I9WyMtPEJv     {
:ak H$p3tI       if(pHead->sFreelistIndex[i] == bytes) |5v"@:C9[W7O@\D
        break;
3mu&K&iV     }
(QY'[ RV?J_     std::cout<<"freelist_getindex:bytes="<<bytes<<" , return="<<i<<std::endl;
x @+Y k\l{HQ)|!d     return i; #JT7UO`} C:O
  };
v&D(s+B.al,LA)iRN   template <class T>
e2WJ.D$HUsqNd   char* MyAlloc<T>::chunk_alloc(int size, int *nobjs)
x*[)J1u8UC~J"R   { &BkyK)u:Q ?.C
    char* result; s]E K}k*`{-su3F
    int counts = *nobjs; $t8e8T$LC W+|n
    int total_bytes = size * counts;
g s6m a*t     int bytes_left = int(pHead->pEndfree - pHead->pStartfree); Kb7SF r'}
    std::cout<<"chunk_alloc:total_bytes = "<<total_bytes
R(k(e"^NQ4V^d       <<",bytes_left = "<<bytes_left<<std::endl;
3} K/~Qa$FM w5Xc-P'U     if (bytes_left >= total_bytes)
`4{AyAN7k0Sw y     { 8e)X$G)m2i-K
      result = pHead->pStartfree; *fBK5]1PMt
      pHead->pStartfree += total_bytes; nl,}Uy{#S3~ b
      std::cout<<"chunk_alloc:total_bytes = "<<total_bytes
CuOD VIV2p         <<",result = "<<*result<<",start_free = "<<&(pHead->pStartfree)<<std::endl; eIL2??"f3F~
    }
%QeN,` O     else if (bytes_left >= size) n!XcX@{q&]kn
    { 9d3n0dC9v_@-U
      counts = bytes_left/size; ` k2d-u*u(Q~
      total_bytes = size * counts; I~$? P/?$h8ey
      result = pHead->pStartfree; 7vVrK'i
      pHead->pStartfree += total_bytes; qG;a+p#NxuD!]
      *nobjs = counts; +cd$IO^9v
      std::cout<<"chunk_alloc:total_bytes = "<<total_bytes<<",nobjs = "<<nobjs
q*J7QZZ]#a         <<",result = "<<*result<<",start_free = "<<&(pHead->pStartfree)<<std::endl; `EE2q6lH4_}
    }
;V&M(_?e     else
+|y%vc{1@0@(s jH     { H3w_EkH
      /*还需要处理回收其他空闲freelist里面的空间*/
v'vJ@:A%d'_ Nu       result = NULL;
%B9E+a6D(^ i!tD K     } ;X\sB#?v.E$G%e
    return(result); 3fO9K9[N%Z&hQ
  };
"V!_0F~ ?`2j.z   template <class T>
T(L+qi&O   void* MyAlloc<T>::refill(int num,int n)
8Wn*y:N|   { #^ _]#g ]K-U
    int counts = num;
(d"JX!|)R:j;A`E     int *nobjs = &counts; qo6i};~l(v vNT
    char* chunk; JBH+@ ~9P ~
    Obj** my_free_list;
i*M5J'?:h#v~q     Obj* result;
_v pWP+] F#y     Obj* current_obj;
%y_ _ n.gV.Z     Obj* next_obj;
-m C|8x#c n])E     int i;
S[n:js}P@     chunk = chunk_alloc(n, nobjs); .b0i'wFu*ZY
    if(chunk == NULL) jpw3XjTf~
    {
W1dr6U2p       return(chunk);
n U-z]2xK2t(D1N%u%Wko     } n1`t+eK:] [,g
    counts = *nobjs; :Bf2@0V:B.X&|)[
    if (1 == counts)
:V,Rn M7n.H     {
~ @mQD       return(chunk); ]4RO(w8{V
    }
&^l J:[ T     my_free_list = pHead->uFreelist + freelist_index(n);
6w]{`qk%Y#Oc-k]     result = (Obj*)chunk; vvqk1j5Y
    *my_free_list = next_obj = (Obj*)(chunk + n*num);
;dvDDErOt     for (i = 1; ; i++) )M4WC[&s
    { ){ ZNq2a*A0j
      current_obj = next_obj; 8h'\ de-Qq*V
      next_obj = (Obj*)((char*)next_obj + n);
g{!krzp}(Q       if (counts - 1 == i)
][1i qZq       { '^(Uuw5z;g'C
        current_obj->M_free_list_link = 0; IsW:U!S#G*}q
        break; 5\%z-Dt*pa5i a
      } u*bQE*S5a6y,]
      else Mc#ldP.U ^b
      {
-zHS;Qfx^5@,`{z         current_obj->M_free_list_link = next_obj; fS z ^!XDrbM(u
      } G8xQ(Q"l2T-f
    } K-vlr:`0K:Np
    return(result);
$_z@(\$]#c-l/~   };
$[(H1Nu#c Ag /*这个函数可以改写成自己的共享内存分配函数*/   
$GG{#uZR static void InitShm() #tV]Rsy'Kh
  {
7Y]x)d$\2kd/r"br     int i,size=1000; 0JI-L+{$x
    pHead = (Cookie*)malloc(sizeof(Cookie)+size); 4}"To0K/y/t
    pHead->iTotalsize = sizeof(Cookie)+size; N!nka#uRj;P8v
    pHead->pStartall  = pHead; D0aY/F|._4j$M
    pHead->pStartfree = (char*)pHead + sizeof(Cookie);
p qwI.~ dE0e     pHead->pEndfree   = (char*)pHead + pHead->iTotalsize; ]:f[~O\
    for(i=0 ; i <NODENUMS ; i++) 1H)vi5zgC$N9OT
    { Z]SD*T$V!\G
      pHead->sFreelistIndex[i]=0;
5N0Y `"WgU"e7{       pHead->uFreelist[i]=0; }i A#Gx O l&H
      pHead->iUseNum[i]=0;
?bbC%Yt-f^%w%[x'K     } "{g:W*It3F*A
  }
:A*yG,]Pt.t   static void PrintFreelistAndCookie()
rld#b3}&j   {
e3G`$LufMqV ekv_     int i,j; %d L7]H `o M]J
    Obj* my_free_list;
v(\n4f%h ]N*~S~0O%S     std::cout<<"Cookie info :"<<std::endl; !|p*bx;t$L&hJ,~t n9M
    std::cout<<"sizeof(struct Cookie) = "<<sizeof(Cookie)<<std::endl;
R@;j%Tb2hv     std::cout<<"Totalsize     = "<<pHead->iTotalsize<<std::endl; NCl6wC8i2M/oc
    std::cout<<"UsedSize      = "<<int(pHead->pStartfree-(char*)pHead)<<std::endl;
l \lG k ri"B0v     std::cout<<"FreepoolSize  = "<<int(pHead->pEndfree - pHead->pStartfree)<<std::endl; a&x*h V H0^6MR5] L%A
    std::cout<<"Startall      = "<<&(pHead->pStartall)<<std::endl;
6~tq1q d;@-t,~     std::cout<<"Startfree     = "<<&(pHead->pStartfree)<<std::endl;
9i d-O,r-h tN     std::cout<<"Endfree       = "<<&(pHead->pEndfree)<<std::endl;
3yWg,{P;Vk/DF     std::cout<<"nFreelist info :"<<std::endl;
'qd(I a;T7m-|K}     for(i=0 ; i<NODENUMS ; i++) `(l e/`F-q6gwj
    { ;jj@ip
      j=0; C*|j]$L @,L!z
      std::cout<<"iUseNum["<<i<<"] = "<<pHead->iUseNum[i]<<std::endl;
5n0?E.S)wKO       std::cout<<"FreelistIndex["<<i<<"] = "<<pHead->sFreelistIndex[i]<<std::endl; u(l#d8]l@am
      my_free_list = pHead->uFreelist[i];
z9Wm5^H^n6P       if(my_free_list->M_client_data != 0)
&`IO"tIf       { If%l2O }b3f
        while(my_free_list->M_client_data != 0) @#BSx%d m Bn3r1iY
        { IsnRob8j
          j++;
se3OM8z           my_free_list = my_free_list->M_free_list_link; HiDbQ+H
        } lV1D#\8R9H:R&O({^
        std::cout<<"free_list["<<i<<"]; node counts="<<j<<std::endl; 3W0v4a&hY(v
      } Z8@.cr3@`Qa
    }
_vXJ1zI3~   }
YdY d m9fZ k(C"\   template <class T1, class T2>
&L-D*}s.w)LM?   bool operator== (const MyAlloc<T1>&,const MyAlloc<T2>&) throw()  {|K%p`(H
  {
T"D y%FI\:G+f8}'U     return true; ~ QxP|Z)ZJX
  }
e*S ^1r ?%e   template <class T1, class T2>
!X,w f-g x;g+P1J   bool operator!= (const MyAlloc<T1>&,const MyAlloc<T2>&) throw()  
(g+Y}|$}*{^;o   {
)Pyk-a|3aVjF     return false; G XXt QyR d&w%r
  } OfM6~0QNq
}
8t)aK.p)} h Q.`8Oo2L #endif /*MY_ALLOCATOR_H_*/
5{:^l/BA,|Y W(~d0QT 测试程序的源码如下:
"^0A&Wc z ca2};FB T/XQ0kM2}I
// MyStl.cpp : 定义控制台应用程序的入口点。 )Nn8[!f`nR
//
p*dV-?x0_ |&}} #include "stdafx.h"
)_? v2{Q7E'E m7` VG #include <map>
/^s0N(_L.T#V #include <vector> 9n mY3[8p [
#include <string>
3CezzH l@f #include <utility>
h.B)G,~8` ]8b2c&rZ #include <iostream>
`o)~'i;k&o5[2K/J:h #include "MyAlloc.h"
Evfu[#s5M using namespace std; f,bZF O X IY
int _tmain(int argc, _TCHAR* argv[]) DHk7^ }
{ #G4S4_ Vb4q
  happyever ::InitShm();
E[:HU(z"~8T%fG   multimap<string,int,less<string>,happyever ::MyAlloc<string> > m;
#v e+Cl!`;T \9d*s   m.insert(make_pair(string("Harry"), 32)); o#MB1Z(?bBA
  m.insert(make_pair(string("Mary"), 59)); p8pz2Y |*]I
  m.insert(make_pair(string("Roger"), 18));
;u,?Kh)YDu j   m.insert(make_pair(string("Nancy"), 37));
K+\ea2o   m.insert(make_pair(string("Mary"), 23));
:o^2KYvB/fO    '~(C7LW O#e sVp*of-u
  typedef multimap<string,int,less<string>,happyever ::MyAlloc<string> >::iterator Iter; ;Dn2h+oJ-r KY.R k
  for (Iter p = m.begin(); p != m.end(); p++) 9[:}S9P X$e
  { 4PD+r[+[%i6f
    cout << p->first << "," << p->second << endl; y qH$D v
  }
|i"oAr5d   Iter p = m.find("Harry");
0}o-F"@)ri   m.erase(p);
py udeT,A/d$s   /*p = m.find("Harry"); ^9H_S:]*D5F7On5c
  cout << "Harry is: " << p->second << "." << endl;*/
~7J9w5oo
0l3xzD7oi-H   for (Iter p = m.begin(); p != m.end(); p++) /xc W$q}t OA
  { !nl'cKh
    cout << p->first << "," << p->second << endl; $VH.`8G Z7C3{$Y?k
  }
t$e,~'`W#g7t    
,[&@A+R)l!dF   return 0; 6Q&oi:rnm5ZdM(|
}
$@`*B0D1wM kV6p 以上程序在vs2005,vc6上测试通过。使用MinGW编译的时候只需要去掉vc的预编译头文件 Es/y\3NU6e4_E
#include "stdafx.h"
~f%o~e1J,qQ
+}AWQ1L%OJJ
tF6E8H\K0Y4R,XP   即可。
(G)O;X,H'n*BN 0fc u6G8^6q}d
  以上程序只要稍微修改,就可以实现共享内存的管理,可以方便的使用标准库提供的容器。加上信号量的锁机制。/k7xQk)N-D
t4x o{z n
  以上为了学习而改写的SGI的stl二级分配算法实现的。以上代码存在一定的局限性。我另外完整实现了共享内存管理的STL标准的alloctor程序,使用posix信号量加锁。目前应用在aix的xlC编译环境下。因为源码涉及公司的商业秘密,所以不能公开。但基本上以上源码已经体现了自己管理内存的完整思路,供这方面需求的朋友一起学习研究用。

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.