<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      CLR內(nèi)核調(diào)試之:Malloc函數(shù)實(shí)現(xiàn)

               自從可以動(dòng)態(tài)調(diào)試SSCLI之后,發(fā)現(xiàn)這個(gè)玩意還真是個(gè)寶山,越玩越有意思,就像捅開(kāi)一扇門(mén),發(fā)現(xiàn)門(mén)后面還有一座寶山……不光CLR的內(nèi)部實(shí)現(xiàn)細(xì)節(jié),可以象是放電影一樣呈現(xiàn)在眼前,Visual Studio里面的一些底層的技術(shù),還有OS的底層技術(shù),查看起來(lái)那是相當(dāng)?shù)谋憬荨?/span>

               這里就說(shuō)說(shuō)malloc函數(shù)是具體如何實(shí)現(xiàn)的,能夠F10,F11動(dòng)態(tài)的在VS里面跟蹤其一步一步的實(shí)現(xiàn)的源碼,真是一件痛快的事情。

       

               為嘛要說(shuō)malloc的實(shí)現(xiàn)呢?因?yàn)樵?/span>main開(kāi)始以后,要為傳遞進(jìn)來(lái)的參數(shù)分配內(nèi)存地址。而這個(gè)時(shí)候我不小心按了F11,不小心看到了malloc是具體如何運(yùn)作的:

              

               Clix.cppint __cdecl main(int argc, char **argv)之后,

               首先得到參數(shù)行,然后分配一個(gè)空間把這個(gè)參數(shù)行保存起來(lái):

       

          pwzCmdLine = ::GetCommandLineW();

          // Allocate for the worst case storage requirement.

      WCHAR *pAlloc = (WCHAR*)malloc((wcslen(pwzCmdLine) + 1) * sizeof(WCHAR));

       

      首先獲得到命令行,然后使用malloc分配ygie空間給存起來(lái)。sizeof(WCHAR)的含義ms是在后面加上一個(gè)終止的標(biāo)記。

      Malloc函數(shù),首先跳轉(zhuǎn)到了d:\Rotor\sscli20\pal\win32\win32pal.c下:

      One:

      PALIMPORT

      void *

      __cdecl

      PAL_malloc(size_t bytes)

      {

               //mark how much bytes had successful allocated.

          void *Ret;

          LOGAPI("malloc(bytes=%p)\n", bytes);

          Ret = malloc(bytes);

       

          LOGAPI("malloc returns void* %p\n", Ret);

          return Ret;

      }

      這是一個(gè)PAL_malloc,是sscli里面針對(duì)特定的操作系統(tǒng)的PAL層的實(shí)現(xiàn),因?yàn)槲矣玫氖遣僮飨到y(tǒng)是Windows XP En,這里就開(kāi)始調(diào)用操作系統(tǒng)里面的malloc的實(shí)現(xiàn)了,在看malloc之前,先看看LOGAPI是干嘛的:

      Two

      void

      __cdecl

      PalLogApi(const char *fmt,...)

      {

          va_list list;

          // Assert that the PAL APIs are only being called when the PAL

          // is properly initialized.

       

          // This assert is disabled because of gcc startup code calls Win32 functions before calling PAL initialize.

      // PALASSERT(PalReferenceCount != 0);

       

          if (LogFileHandle == INVALID_HANDLE_VALUE) {

              // Logging isn't enabled

              return;

          }

          va_start(list, fmt);

          PalLogApiCore(fmt, list);

          va_end(list);

      }

               首先,我很奇怪C++里面的是個(gè)怎么樣子的參數(shù)傳遞方法….

               打開(kāi)一看,咱就知道了,這個(gè)是和SSCLI的調(diào)試功能緊密結(jié)合在一起的。下面截圖了個(gè):

       

       

               這下看到了,LogFileHandle表示如果開(kāi)啟了SSCLIlog功能,就把這次malloc的情況給記錄下來(lái)。

      然后這里沒(méi)有開(kāi)啟LOG功能,這個(gè)變量就是0xfffffff,然后就直接return了。繼續(xù)回到One里面的Ret = malloc(bytes);這個(gè)地方。這個(gè)方法的目的,是Allocate of block of memory of at least size bytes from the heap and return a pointer to it.下跳轉(zhuǎn)到了Malloc的本地實(shí)現(xiàn)了,到了文件:

      Three

      C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\dbgmalloc.c

       

      extern "C" _CRTIMP void * __cdecl malloc (size_t nSize)

      {

              void *res = _nh_malloc_dbg(nSize, _newmode, _NORMAL_BLOCK, NULL, 0);

       

              RTCCALLBACK(_RTC_Allocate_hook, (res, nSize, 0));

              return res;

      }

       

      然后繼續(xù)看調(diào)用的_nh_malloc_dbg來(lái)如何實(shí)現(xiàn)內(nèi)存的分配,這下來(lái)到了

      C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\dbgheap.c,這個(gè)文件中:

      Four

      extern "C" void * __cdecl _nh_malloc_dbg (

              size_t nSize,

              int nhFlag,

              int nBlockUse,

              const char * szFileName,

              int nLine

              )

      {

              int errno_tmp = 0;

              void * pvBlk = _nh_malloc_dbg_impl(nSize, nhFlag, nBlockUse, szFileName, nLine, &errno_tmp);

       

              if ( pvBlk == NULL && errno_tmp != 0 && _errno())

              {

                  errno = errno_tmp; // recall, #define errno *_errno()

              }

              return pvBlk;

      }

       

      從名字上來(lái)看,是在Debug heap上面給分配的空間。這個(gè)方法的purpose,is Allocate of block of memory of at least size bytes from the debug heap and return a pointer to it. Assumes heap already locked.If no blocks available, call new handler.Allocates any type of supported memory block.

      Five

      extern "C" static void * __cdecl _nh_malloc_dbg_impl (

              size_t nSize,

              int nhFlag,

              int nBlockUse,

              const char * szFileName,

              int nLine,

              int * errno_tmp

              )

      {

              void * pvBlk;

              for (;;)

              {

                  /* do the allocation*/

                  pvBlk = _heap_alloc_dbg_impl(nSize, nBlockUse, szFileName, nLine, errno_tmp);

                  if (pvBlk)

                  {

                      return pvBlk;

                  }

                  if (nhFlag == 0)

                  {

                      *errno_tmp = ENOMEM;

                      return pvBlk;

                  }

       

                  /* call installed new handler */

                  if (!_callnewh(nSize))

                  {

                      *errno_tmp = ENOMEM;

                      return NULL;

                  }

                  /* new handler was successful -- try to allocate again */

              }

      }

      _nh_malloc_dbg_impl()這個(gè)方法,主要是在Debug heap上面分配一段的memory,同時(shí)返回一個(gè)指向它的指針,同時(shí),假設(shè)這個(gè)heap已經(jīng)被lock了。這里,又跳轉(zhuǎn)到了_heap_alloc_dbg_impl,唉,我等的花都謝了,還是這個(gè)文件里面,終于,在這里看到了實(shí)際的內(nèi)存分配的過(guò)程:

      Six:

      extern "C" static void * __cdecl _heap_alloc_dbg_impl(

              size_t nSize,

              int nBlockUse,

              const char * szFileName,

              int nLine,

              int * errno_tmp

              )

      {

              long lRequest;

              size_t blockSize;

              int fIgnore = FALSE;

              _CrtMemBlockHeader * pHead;

              void *retval=NULL;

       

              /* lock the heap*/

              _mlock(_HEAP_LOCK);

              __try {

                  /* verify heap before allocation */

                  if (check_frequency > 0)//false

                      if (check_counter == (check_frequency - 1))

                      {

                          _ASSERTE(_CrtCheckMemory());

                          check_counter = 0;

                      }

                      else

                          check_counter++;

                  lRequest = _lRequestCurr;

       

                  /* break into debugger at specific memory allocation */

                  if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc)//false

                      _CrtDbgBreak();

       

                  /* forced failure */

                  if ((_pfnAllocHook) && !(*_pfnAllocHook)(_HOOK_ALLOC, NULL, nSize,

      nBlockUse, lRequest, (const unsigned char *)szFileName, nLine)) //false

                  {

                      if (szFileName)

                          _RPT2(_CRT_WARN, "Client hook allocation failure at file %hs line %d.\n",

                              szFileName, nLine);

                      else

                          _RPT0(_CRT_WARN, "Client hook allocation failure.\n");

                  }

                  else

                  {

                      /* cannot ignore CRT allocations */

                      if (_BLOCK_TYPE(nBlockUse) != _CRT_BLOCK &&

                          !(_crtDbgFlag & _CRTDBG_ALLOC_MEM_DF)) //false

                          fIgnore = TRUE;

       

                      /* Diagnostic memory allocation from this point on */

                      if (nSize > (size_t)(_HEAP_MAXREQ - nNoMansLandSize - sizeof(_CrtMemBlockHeader))) //false

                      {

                          _RPT1(_CRT_ERROR, "Invalid allocation size: %Iu bytes.\n", nSize);

                          *errno_tmp = ENOMEM;

                      }

                      else

                      {

                          if (!_BLOCK_TYPE_IS_VALID(nBlockUse)) //false

                          {

                              _RPT0(_CRT_ERROR, "Error: memory allocation: bad memory block type.\n");

                          }

       

                          blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;

       

                          RTCCALLBACK(_RTC_FuncCheckSet_hook,(0));

      //acture called:

      //return HeapAlloc(_crtheap, 0, size ? size : 1);

                          pHead = (_CrtMemBlockHeader *)_heap_alloc_base(blockSize);

       

                          if (pHead == NULL) //false

                          {

                              *errno_tmp = ENOMEM;

                              RTCCALLBACK(_RTC_FuncCheckSet_hook,(1));

                          }

                          else

                          {

       

                              /* commit allocation */

                              ++_lRequestCurr;

       

                              if (fIgnore) //false

                              {

                                  pHead->pBlockHeaderNext = NULL;

                                  pHead->pBlockHeaderPrev = NULL;

                                  pHead->szFileName = NULL;

                                  pHead->nLine = IGNORE_LINE;

                                  pHead->nDataSize = nSize;

                                  pHead->nBlockUse = _IGNORE_BLOCK;

                                  pHead->lRequest = IGNORE_REQ;

                              }

                              else {

                                  /* keep track of total amount of memory allocated */

                                  if (SIZE_MAX - _lTotalAlloc > nSize)

                                  {

                                      _lTotalAlloc += nSize;

                                  }

                                  else

                                  {

                                      _lTotalAlloc = SIZE_MAX;

                                  }

                                  _lCurAlloc += nSize;

       

                                  if (_lCurAlloc > _lMaxAlloc)

                                  _lMaxAlloc = _lCurAlloc;

       

                                  if (_pFirstBlock) //false

                                      _pFirstBlock->pBlockHeaderPrev = pHead;

                                  else

                                      _pLastBlock = pHead;

       

                                  pHead->pBlockHeaderNext = _pFirstBlock;

                                  pHead->pBlockHeaderPrev = NULL;

                                  pHead->szFileName = (char *)szFileName;

                                  pHead->nLine = nLine;

                                  pHead->nDataSize = nSize;

                                  pHead->nBlockUse = nBlockUse;

                                  pHead->lRequest = lRequest;

                                                                       //the type of pHead is _CrtMemBlockHeader *

       

                                  /* link blocks together */

                                  _pFirstBlock = pHead;

                              }

       

                              /* fill in gap before and after real block */

                                                              //memset founction is usually used to set a gap of mem to a certain char, usually used for initial memory.

                              memset((void *)pHead->gap, _bNoMansLandFill, nNoMansLandSize);

                              memset((void *)(pbData(pHead) + nSize), _bNoMansLandFill, nNoMansLandSize);

       

                              /* fill data with silly value (but non-zero) */

                              memset((void *)pbData(pHead), _bCleanLandFill, nSize);

       

                              retval=(void *)pbData(pHead);

                          }

                      }

                  }

              }

              __finally {

                  /* unlock the heap */

                  _munlock(_HEAP_LOCK);

              }

              return retval;

      }

              

               先看看_mlock(_HEAP_LOCK);是如何實(shí)現(xiàn)的:

      void __cdecl _lock (

              int locknum

              )

      {

              /*

               * Create/open the lock, if necessary

               */

              if ( _locktable[locknum].lock == NULL ) {

                  if ( !_mtinitlocknum(locknum) )

                      _amsg_exit( _RT_LOCK );

              }

              /*

               * Enter the critical section.

               */

              EnterCriticalSection( _locktable[locknum].lock );

      }

       

      看到了傳說(shuō)中的locktable,截圖留念下:

       

       

      也得到了Locktable是如何操作的方法,如上面所示

       

      Six:中,我標(biāo)出了每個(gè)if判斷的時(shí)候所走的分支。做好了這一切之后,分配好了空間就一步一步返回了。最后提下memset方法,鏈接到了C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\src\INTEL\memset.asm中,一大段匯編代碼來(lái)移動(dòng)內(nèi)存。主要用來(lái)做內(nèi)存的初始化的時(shí)候用。

       

      Lbq1221119@cnblogs first post at http://sscli.cnblogs.com

      2008-11-12 10:35:22 PM

       

       

      posted on 2008-11-13 20:52  lbq1221119  閱讀(5673)  評(píng)論(11)    收藏  舉報(bào)

      導(dǎo)航

      主站蜘蛛池模板: 国产亚洲精品第一综合| 国精偷拍一区二区三区| 国产suv精品一区二区883| 免费观看一级欧美大| 桃花岛亚洲成在人线AV| 国产高清精品在线91| 国产精品一区二区传媒蜜臀| 中文字幕国产在线精品| 亚洲欧美偷国产日韩| 亚洲国产午夜精品福利| 99精品国产中文字幕| 久久热这里只有精品最新| 91精品国产免费人成网站| 国产精品国产三级国产午| 最新偷拍一区二区三区| 栾川县| 国产国拍精品av在线观看| 亚洲乱码中文字幕小综合| 容城县| 少妇做爰免费视看片| 丁香花在线影院观看在线播放 | 平江县| 中文字幕免费不卡二区| 亚洲精品网站在线观看不卡无广告| 国产精品中文字幕在线| 国产mv在线天堂mv免费观看| 日韩国产成人精品视频| 国产成人综合在线女婷五月99播放 | 美女一区二区三区亚洲麻豆| 潮喷无码正在播放| 亚洲一本大道在线| 日韩av日韩av在线| 日韩精品国产中文字幕| 亚洲精品乱码久久久久久中文字幕| 国产 浪潮av性色四虎| 剑阁县| 大方县| 无码专区视频精品老司机 | 国产精品不卡区一区二| 国产老熟女无套内射不卡| 无码国内精品久久人妻蜜桃|