粗解“new”之来龙去脉(二)
来源:互联网 发布:2017店铺淘宝客怎么做 编辑:程序博客网 时间:2024/05/27 16:42
接着往下走看看_heap_alloc_base这个函数
#define MAX_ALLOC_DATA_SIZE 0x3f8#define BYTES_PER_PARA 16size_t __sbh_threshold = MAX_ALLOC_DATA_SIZE;void * __cdecl _heap_alloc_base (size_t size){#ifdef WINHEAP void * pvReturn;#else /* WINHEAP */ _PBLKDESC pdesc; _PBLKDESC pdesc2;#endif /* WINHEAP */#ifdef WINHEAP if (size <= __sbh_threshold) { _mlock(_HEAP_LOCK); pvReturn = __sbh_alloc_block(size); _munlock(_HEAP_LOCK); if (pvReturn) return pvReturn; } if (size == 0) size = 1; size = (size + BYTES_PER_PARA - 1) & ~(BYTES_PER_PARA - 1); return HeapAlloc(_crtheap, 0, size);}
我们可以看出,如果请求分配的内存大小小等于__sbh_threshold (默认值是0x3f8)的话,则调用__sbh_alloc_block去获得地址,如果大于的话则调用HeapAlloc去分配,其中__sbh_threshold值也是可以设置得,但必需是小于0x3f8的。
int __cdecl _set_sbh_threshold (size_t threshold){ // test against maximum value - if too large, return error if (threshold > MAX_ALLOC_DATA_SIZE) return 0; // set the threshold value __sbh_threshold = threshold; return 1;}
我们还可以看出如果大小为0的话,会设置size = 1,也就是说如果我们去new一个大小为0的地址也会成功,会自动把它大小设置为1.当然还有一些别的附加内容。
对HeapAlloc的分析不再继续往下进行,因为我找不到它的源代码。我们接着看调用__sbh_alloc_block如何分配。
typedef unsigned int BITVEC;typedef struct tagRegion{ int indGroupUse; char cntRegionSize[64]; BITVEC bitvGroupHi[GROUPS_PER_REGION]; BITVEC bitvGroupLo[GROUPS_PER_REGION]; struct tagGroup grpHeadList[GROUPS_PER_REGION];}REGION, *PREGION;typedef struct tagHeader{ BITVEC bitvEntryHi; BITVEC bitvEntryLo; BITVEC bitvCommit; void * pHeapData; struct tagRegion * pRegion;}HEADER, *PHEADER;PHEADER __sbh_pHeaderList; // pointer to list startPHEADER __sbh_pHeaderScan; // pointer to list roverint __sbh_sizeHeaderList; // allocated size of listint __sbh_cntHeaderList; // count of entries defined#define BYTES_PER_PARA 16void * __cdecl __sbh_alloc_block (int intSize){ PHEADER pHeaderLast = __sbh_pHeaderList + __sbh_cntHeaderList; PHEADER pHeader; PREGION pRegion; PGROUP pGroup; PENTRY pEntry; PENTRY pHead; BITVEC bitvEntryLo; BITVEC bitvEntryHi; BITVEC bitvTest; int sizeEntry; int indEntry; int indGroupUse; int sizeNewFree; int indNewFree; // add 8 bytes entry overhead and round up to next para size sizeEntry = (intSize + 2 * sizeof(int) + (BYTES_PER_PARA - 1)) & ~(BYTES_PER_PARA - 1); // determine index and mask from entry size // Hi MSB: bit 0 size: 1 paragraph // bit 1 2 paragraphs // ... ... // bit 30 31 paragraphs // bit 31 32 paragraphs // Lo MSB: bit 0 size: 33 paragraph // bit 1 34 paragraphs // ... ... // bit 30 63 paragraphs // bit 31 64+ paragraphs indEntry = (sizeEntry >> 4) - 1; if (indEntry < 32) { bitvEntryHi = 0xffffffffUL >> indEntry; bitvEntryLo = 0xffffffffUL; } else { bitvEntryHi = 0; bitvEntryLo = 0xffffffffUL >> (indEntry - 32); } // scan header list from rover to end for region with a free // entry with an adequate size pHeader = __sbh_pHeaderScan; while (pHeader < pHeaderLast) { if ((bitvEntryHi & pHeader->bitvEntryHi) | (bitvEntryLo & pHeader->bitvEntryLo)) break; pHeader++; } // if no entry, scan from list start up to the rover if (pHeader == pHeaderLast) { pHeader = __sbh_pHeaderList; while (pHeader < __sbh_pHeaderScan) { if ((bitvEntryHi & pHeader->bitvEntryHi) | (bitvEntryLo & pHeader->bitvEntryLo)) break; pHeader++; } // no free entry exists, scan list from rover to end // for available groups to commit if (pHeader == __sbh_pHeaderScan) { while (pHeader < pHeaderLast) { if (pHeader->bitvCommit) break; pHeader++; } // if no available groups, scan from start to rover if (pHeader == pHeaderLast) { pHeader = __sbh_pHeaderList; while (pHeader < __sbh_pHeaderScan) { if (pHeader->bitvCommit) break; pHeader++; } // if no available groups, create a new region if (pHeader == __sbh_pHeaderScan) if (!(pHeader = __sbh_alloc_new_region())) return NULL; } // commit a new group in region associated with pHeader if ((pHeader->pRegion->indGroupUse = __sbh_alloc_new_group(pHeader)) == -1) return NULL; } } __sbh_pHeaderScan = pHeader; pRegion = pHeader->pRegion; indGroupUse = pRegion->indGroupUse; // determine the group to allocate from if (indGroupUse == -1 || !((bitvEntryHi & pRegion->bitvGroupHi[indGroupUse]) | (bitvEntryLo & pRegion->bitvGroupLo[indGroupUse]))) { // preferred group could not allocate entry, so // scan through all defined vectors indGroupUse = 0; while (!((bitvEntryHi & pRegion->bitvGroupHi[indGroupUse]) | (bitvEntryLo & pRegion->bitvGroupLo[indGroupUse]))) indGroupUse++; } pGroup = &pRegion->grpHeadList[indGroupUse]; // determine bucket index indEntry = 0; // get high entry intersection - if zero, use the lower one if (!(bitvTest = bitvEntryHi & pRegion->bitvGroupHi[indGroupUse])) { indEntry = 32; bitvTest = bitvEntryLo & pRegion->bitvGroupLo[indGroupUse]; } while ((int)bitvTest >= 0) { bitvTest <<= 1; indEntry++; } pEntry = pGroup->listHead[indEntry].pEntryNext; // compute size and bucket index of new free entry // for zero-sized entry, the index is -1 sizeNewFree = pEntry->sizeFront - sizeEntry; indNewFree = (sizeNewFree >> 4) - 1; if (indNewFree > 63) indNewFree = 63; // only modify entry pointers if bucket index changed if (indNewFree != indEntry) { // test entry is sole member of bucket (next == prev), if (pEntry->pEntryNext == pEntry->pEntryPrev) { // clear bit in group vector, decrement region count // if region count is now zero, clear bit in region vector if (indEntry < 32) { pRegion->bitvGroupHi[indGroupUse] &= ~(0x80000000L >> indEntry); if (--pRegion->cntRegionSize[indEntry] == 0) pHeader->bitvEntryHi &= ~(0x80000000L >> indEntry); } else { pRegion->bitvGroupLo[indGroupUse] &= ~(0x80000000L >> (indEntry - 32)); if (--pRegion->cntRegionSize[indEntry] == 0) pHeader->bitvEntryLo &= ~(0x80000000L >> (indEntry - 32)); } } // unlink entry from list pEntry->pEntryPrev->pEntryNext = pEntry->pEntryNext; pEntry->pEntryNext->pEntryPrev = pEntry->pEntryPrev; // if free entry size is still nonzero, reconnect it if (sizeNewFree != 0) { // add entry to the start of the bucket list pHead = (PENTRY)((char *)&pGroup->listHead[indNewFree] - sizeof(int)); pEntry->pEntryNext = pHead->pEntryNext; pEntry->pEntryPrev = pHead; pHead->pEntryNext = pEntry; pEntry->pEntryNext->pEntryPrev = pEntry; // test entry is sole member of bucket (next == prev), if (pEntry->pEntryNext == pEntry->pEntryPrev) { // if region count was zero, set bit in region vector // set bit in group vector, increment region count if (indNewFree < 32) { if (pRegion->cntRegionSize[indNewFree]++ == 0) pHeader->bitvEntryHi |= 0x80000000L >> indNewFree; pRegion->bitvGroupHi[indGroupUse] |= 0x80000000L >> indNewFree; } else { if (pRegion->cntRegionSize[indNewFree]++ == 0) pHeader->bitvEntryLo |= 0x80000000L >> (indNewFree - 32); pRegion->bitvGroupLo[indGroupUse] |= 0x80000000L >> (indNewFree - 32); } } } } // change size of free entry (front and back) if (sizeNewFree != 0) { pEntry->sizeFront = sizeNewFree; ((PENTRYEND)((char *)pEntry + sizeNewFree - sizeof(ENTRYEND)))->sizeBack = sizeNewFree; } // mark the allocated entry pEntry = (PENTRY)((char *)pEntry + sizeNewFree); pEntry->sizeFront = sizeEntry + 1; ((PENTRYEND)((char *)pEntry + sizeEntry - sizeof(ENTRYEND)))->sizeBack = sizeEntry + 1; // one more allocation in group - test if group was empty if (pGroup->cntEntries++ == 0) { // if allocating into deferred group, cancel deferral if (pHeader == __sbh_pHeaderDefer && indGroupUse == __sbh_indGroupDefer) __sbh_pHeaderDefer = NULL; } pRegion->indGroupUse = indGroupUse; return (void *)((char *)pEntry + sizeof(int));}
这个函数使用了一些全局变量需要注意一下,比如使用了__sbh_pHeaderList等,它们的值是什么时候初始化的呢?
- 粗解“new”之来龙去脉(二)
- 粗解“new”之来龙去脉(一)
- 粗解“new”之来龙去脉(三)
- 粗解“new”之来龙去脉(四)
- KMP算法之来龙去脉
- 符号之来龙去脉
- 编码之痛(上)编码的来龙去脉
- MFC来龙去脉(侯捷)
- 【原创】MFC程序设计之来龙去脉
- android事件机制之来龙去脉
- 详解ORACLE ROWID之来龙去脉
- Android输入输出机制之来龙去脉
- android基础学习<二>--->Activity的来龙去脉
- Linux Kernel之Deferred work(Softirq、tasklet、Work queues)来龙去脉浅析
- AppFramework通用数据库访问组件之来龙去脉
- 原码、反码、补码之来龙去脉
- Android学习之Theme的来龙去脉
- Linux Kernel时间子系统之来龙去脉浅析
- c++ 面试宝典
- 微软借XBOX下注TV
- 表数据null值清除
- JQuery验证jsp页面属性是否为空
- pfring(pf_ring)编译安装
- 粗解“new”之来龙去脉(二)
- 一个简单的HTTP并发测试程序
- SCons命令 之 从入门到精通
- 计算机视觉在工业方面的应用
- 获取导入模板存储过程
- 浅谈PPM (Project Portfolio Management) - 4
- Pandaboard上用software rendering方法启动meegotouchhome
- linux FrameBuffer
- vs显示行号