⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fastmm4bcb.cpp.svn-base

📁 Memory Manager for delphi 5-2007. Usefully to find the memory leaks and help for optimalize your mem
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:

        if (FindCodeDataRangeByDataAddr((unsigned)AVTablePtr
          - (sizeof(unsigned) * 4), NULL, &ADataRange))
        {
          //maybe vtableptr
          unsigned * vftPtr = (unsigned *)AVTablePtr;
          unsigned VMFuncAddr = *vftPtr;
          if (((VMFuncAddr >= ADataRange->CodeSecStart)
            && (VMFuncAddr < ADataRange->DataSecStart))
            || (FindCodeDataRangeByCodeAddr(VMFuncAddr, NULL, &ACodeRange)))
          {
            //address of virtual member function is valid
            unsigned varOffset = vftPtr[-2];
            unsigned rttiPtrOffset = vftPtr[-1];
            if (varOffset <= AVTablePtrOffset)
            {
              unsigned rttiPtr = (unsigned)((char *)vftPtr - rttiPtrOffset);
              if ((rttiPtr >= ADataRange->DataSecStart)
                && (((unsigned *)rttiPtr)[-1] == 0))
              { //rtti Ptr is valid
                TypeDescriptorPtr mdtpidPtr = *((TypeDescriptorPtr *)((unsigned *)rttiPtr - 2) - 1);
                if (((unsigned)mdtpidPtr > ADataRange->CodeSecStart)
                  && (((unsigned)mdtpidPtr + (sizeof(TypeDescriptor) - sizeof(GUID)))
                  < ADataRange->DataSecStart))
                { //tpid data in code section
                  if ((mdtpidPtr->Size >= (AVTablePtrOffset + sizeof(void *)))
                    && (mdtpidPtr->Class.VTablePtrOffset == AVTablePtrOffset)
                    && (mdtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
                    && (mdtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
                  { //tpid data valid ?
                    unsigned char * TypeName = (unsigned char *)mdtpidPtr
                                               + mdtpidPtr->Name;
                    if ((((unsigned)TypeName + sizeof(unsigned char) * 2)
                      < ADataRange->DataSecStart) && (*TypeName <= 'z'))
                    {
                      return mdtpidPtr;
                    }
                  }
                }
              }
            }
          }

        }
      }
    }
  }
  return NULL; 
}

//#define CheckVirtualRootBaseFirst //Returned may not be the most derived type

TypeDescriptorPtr __fastcall GetCppVirtualObjectTypeIdPtr(void * APointer, unsigned ASize)
{
  if ((APointer) && (ASize >= sizeof(void *)))
  {
    if (!((unsigned)APointer & (sizeof(void *) - 1)))
    {
      if (!gpModuleCodeDataRanges)
      {
        if (!FillModuleCodeDataRanges())
        {
          return NULL;
        }
      }
      #ifdef CheckVirtualRootBaseFirst
      TypeDescriptorPtr ret = GetCppVirtualObjectTypeIdPtrByVTablePtr(*((void **)APointer), 0);
      if (ret)
      {
        return ret;
      }
      #endif
      PModuleCodeDataRanges ADataRange, ACodeRange;
      unsigned ObjectSize = ASize;
      
      ASize = ASize - (ASize & (sizeof(void *) - 1)) - sizeof(void *);

      unsigned * DataPtr = (unsigned *)((char *)APointer + ASize);

      #ifdef CheckVirtualRootBaseFirst
      while (DataPtr > (unsigned *)APointer)
      #else
      while (DataPtr >= (unsigned *)APointer)
      #endif
      {
        unsigned Data = *DataPtr;
        if ((Data >= LowestDataAddr) && (Data <= HighestDataAddr))
        {
          if (FindCodeDataRangeByDataAddr(Data - (sizeof(unsigned) * 4),
            NULL, &ADataRange))
          {
            //maybe vtableptr
            unsigned * vftPtr = (unsigned *)Data;
            unsigned VMFuncAddr = *vftPtr;
            if (((VMFuncAddr >= ADataRange->CodeSecStart)
              && (VMFuncAddr < ADataRange->DataSecStart))
              || (FindCodeDataRangeByCodeAddr(VMFuncAddr, NULL, &ACodeRange)))
            {
              //address of virtual member function is valid
              unsigned varOffset = vftPtr[-2];
              unsigned rttiPtrOffset = vftPtr[-1];
              unsigned vftPtrOffset = (char *)DataPtr - (char *)APointer;
              if (varOffset <= vftPtrOffset)
              {
                unsigned rttiPtr = (unsigned)((char *)vftPtr - rttiPtrOffset);
                if ((rttiPtr >= ADataRange->DataSecStart)
                  && (((unsigned *)rttiPtr)[-1] == 0))
                { //rtti Ptr is valid
                  TypeDescriptorPtr mdtpidPtr = *((TypeDescriptorPtr *)((unsigned *)rttiPtr - 2) - 1);
                  if (((unsigned)mdtpidPtr > ADataRange->CodeSecStart)
                    && (((unsigned)mdtpidPtr + (sizeof(TypeDescriptor) - sizeof(GUID)))
                    < ADataRange->DataSecStart))
                  { //tpid data in code section
                    if ((mdtpidPtr->Size <= ObjectSize)
                      && (mdtpidPtr->Class.VTablePtrOffset == vftPtrOffset)
                      && (mdtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
                      && (mdtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
                    { //tpid data valid ?
                      unsigned char * TypeName = (unsigned char *)mdtpidPtr
                                                 + mdtpidPtr->Name;
                      if ((((unsigned)TypeName + sizeof(unsigned char) * 2)
                        < ADataRange->DataSecStart) && (*TypeName <= 'z'))
                      {
                        return mdtpidPtr;
                      }
                    }
                  }
                }
              }
            }

          }
        }
        DataPtr--;
      } 
    }
  }
  return NULL;
}


char * __fastcall GetCppVirtualObjectTypeName(void * APointer, unsigned ASize)
{
  TypeDescriptorPtr AtpidPtr = GetCppVirtualObjectTypeIdPtr(APointer, ASize);
  if (AtpidPtr)
  {
    return (char *)AtpidPtr + AtpidPtr->Name;
  }
  else {
    return NULL;
  }
}

char * __fastcall GetCppVirtualObjectTypeNameByVTablePtr(void * AVTablePtr,
  unsigned AVTablePtrOffset)
{
  TypeDescriptorPtr AtpidPtr = GetCppVirtualObjectTypeIdPtrByVTablePtr(AVTablePtr,
                       AVTablePtrOffset);
  if (AtpidPtr)
  {
    return (char *)AtpidPtr + AtpidPtr->Name;
  }
  else {
    return NULL;
  }
}

unsigned __fastcall GetCppVirtualObjectSizeByTypeIdPtr(TypeDescriptorPtr AtpidPtr)
{
  if ((AtpidPtr)
    && (AtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
    && (AtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
  {
    return AtpidPtr->Size;
  }
  else {
    return 0;
  }
}

char * __fastcall GetCppVirtualObjectTypeNameByTypeIdPtr(TypeDescriptorPtr AtpidPtr)
{
  if (AtpidPtr)
  {
    return (char *)AtpidPtr + AtpidPtr->Name;
  }
  else {
    return NULL;
  }
}

#endif //CheckCppObjectTypeEnabled

#define BORLANDMM "borlndmm"

#define CRTL_MEM_SIGNATURE_EXPORT "___CRTL_MEM_GetBorMemPtrs"
#define CRTL_GET_HEAP_REDIRECTOR_INFO "__get_heap_redirector_info"

bool __fastcall TryHookRTLHeapRedirector(HMODULE AModule, void *AParam)
{
  if ((FindResource(AModule, DVCLALResName, RT_RCDATA))
	/*&& (GetProcAddress(AModule, CPPdebugHookExport))*/
	&& (GetProcAddress(AModule, CRTL_MEM_SIGNATURE_EXPORT)))
  {
	rtl_get_heap_redirector_info_func rtl_get_heap_redirector_info;
	rtl_get_heap_redirector_info
	  = (rtl_get_heap_redirector_info_func)GetProcAddress(AModule, CRTL_GET_HEAP_REDIRECTOR_INFO);
	if (rtl_get_heap_redirector_info)
	{
	  HeapRedirector * pHRDir = (*rtl_get_heap_redirector_info)();
	  if (pHRDir)
	  {
		if ((pHRDir->flags < hrfBorlndmm) || (pHRDir->flags == hrfVCLSystem))
		{
		  void * PatchAddr;

		  HeapRedirectorStorePtr node = (HeapRedirectorStorePtr)FinalGetMem(sizeof(HeapRedirectorStore));
		  node->Data = *pHRDir;
		  node->Module = AModule;
		  
		  //insert node into store list
		  node->Next = HeapRedirectorStoreListHeader;
		  HeapRedirectorStoreListHeader = node;

		  pHRDir->malloc = &Cpp_malloc_Stub;
		  pHRDir->free = &Cpp_free_Stub;
		  pHRDir->realloc = &Cpp_realloc_Stub;
		  pHRDir->terminate = &Cpp_terminate_Stub;
		  pHRDir->flags = hrfOther;

		  pHRDir->allocated = 1;

          //patch RTL _terminate of this module
		  PatchAddr = GetProcAddress(AModule, _terminateExport);
		  if ((PatchAddr) && (((PRelativeJmp32)PatchAddr)->JmpInst != RelativeJmp32Inst)
			&& (!PatchProc(PatchAddr, &New_terminate, &node->PatchBackup)))
		  {
			node->PatchAddress = PatchAddr;
		  }
		  else
		  {
			node->PatchAddress = NULL;
		  }
		}
	  }
	}
  }
  
  return true;
}

bool __fastcall TryUnhookRTLHeapRedirector(HMODULE AModule, void *AParam)
{
  if ((FindResource(AModule, DVCLALResName, RT_RCDATA))
	/*&& (GetProcAddress(AModule, CPPdebugHookExport))*/
	&& (GetProcAddress(AModule, CRTL_MEM_SIGNATURE_EXPORT)))
  {
	rtl_get_heap_redirector_info_func rtl_get_heap_redirector_info;
	rtl_get_heap_redirector_info
	  = (rtl_get_heap_redirector_info_func)GetProcAddress(AModule, CRTL_GET_HEAP_REDIRECTOR_INFO);
	if (rtl_get_heap_redirector_info)
	{
	  HeapRedirector * pHRDir = (*rtl_get_heap_redirector_info)();
	  if (pHRDir)
	  {
		//restore and remove store node
		{
		  HeapRedirectorStorePtr prev, node;

		  prev = NULL;
		  node = HeapRedirectorStoreListHeader;
		  while (node)
		  {
			if (node->Module == AModule)
			{
			  //restore original heap redirector
			  if ((pHRDir->flags == hrfOther)
				&& (pHRDir->malloc == &Cpp_malloc_Stub)
				&& (pHRDir->free == &Cpp_free_Stub)
				&& (pHRDir->realloc == &Cpp_realloc_Stub)
				&& (pHRDir->terminate == &Cpp_terminate_Stub)
				)
			  {
			  #ifdef DetectMMOperationsAfterUninstall
				if ((bool)AParam)
				{
				  pHRDir->malloc = &Cpp_Invalid_malloc_Stub;
				  pHRDir->free = &Cpp_Invalid_free_Stub;
				  pHRDir->realloc = &Cpp_Invalid_realloc_Stub;
				}
				else
			  #endif
				  *pHRDir = node->Data;
			  }

			  //restore RTL _terminate of this module
			  if (node->PatchAddress) 
			  {
				UnPatchProc(node->PatchAddress, &New_terminate, &node->PatchBackup);
			  }

			  //remove node from store list
			  if (prev)
			  {
				prev->Next = node->Next;
			  }
			  else
			  {
				HeapRedirectorStoreListHeader = node->Next;
			  }

			  FinalFreeMem(node);

			  break;
			}
			else
			{
			  prev = node;
			  node = node->Next;
			}
		  }
		}
	  }
	}
  }

  return true;
}

#endif //PatchBCBTerminate


void BCBInstallFastMM()
{
//#ifdef __DLL__ //not defined even with -tWD ?
//#endif

//#if ((!defined(_NO_VCL)) && defined(__DLL__) && defined(_RTLDLL))
   //borlndmm.dll will linked in
//#else
  InitializeMemoryManager();
  #if __BORLANDC__ >= 0x582
  //>= BDS2006 ?
    //CheckCanInstallMemoryManager will finally call System.GetHeapStatus which is the
    //internal shipped copy of FastGetHeapStatus routine, but the InitializeMemoryManager
    //routine of that copy is not called yet at this point, and thus System.GetHeapStatus
    //will generate an access violation exception.
    //Currently avoid this exception by skip the check
    #ifndef _NO_VCL
    if (CheckCanInstallMemoryManager())
    #endif //!_NO_VCL
  #else
  if (CheckCanInstallMemoryManager())
  #endif //< BDS2006
  {
    #ifdef PatchBCBTerminate
      #if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
	  //if FastMM_FullDebugMode.dll receive DLL_PROCESS_DETACH before
	  //calling FinalizeMemoryManager, exception will occur when calling
	  //LogStackTrace in FastMM_FullDebugMode.dll, the following call
	  //will delay the processing of DLL_PROCESS_DETACH in DllMain of
	  //FastMM_FullDebugMode.dll
	  if (!TryHookFullDebugModeDllEntry())
	  {
	    return;
	  }
      #endif
	#endif

    #ifdef FullDebugMode
      #ifdef ClearLogFileOnStartup
        DeleteEventLog();
      #endif //ClearLogFileOnStartup
    #endif //FullDebugMode

    #ifdef PatchBCBTerminate
    #if __BORLANDC__ >= 0x582
    //>= BDS2006 ?
    System::TMemoryManagerEx AMemoryManager;
    #else
    System::TMemoryManager AMemoryManager;
    #endif
    System::GetMemoryManager(AMemoryManager);
    StockGetMemPtr = AMemoryManager.GetMem;
    #endif

	InstallMemoryManager();
  
#ifdef PatchBCBTerminate
	IsMMInstalled = true;
#endif

	#ifdef PatchBCBTerminate

	HMODULE ThisModule = (HMODULE)System::FindHInstance(&BCBInstallFastMM);
	HMODULE MainModule = GetModuleHandle(0);

	//#ifndef _RTLDLL
	HMODULE BorlandMM_Module = GetModuleHandle(BORLANDMM);
	if (!BorlandMM_Module)
	{
	  pHRDir = _get_heap_redirector_info();
	  if (pHRDir)
	  {
		if ((pHRDir->flags < hrfBorlndmm) || (pHRDir->flags == hrfVCLSystem))
		{
		  Old_heap_redirector = *pHRDir;

		  pHRDir->malloc = &Cpp_malloc_Stub;
		  pHRDir->free = &Cpp_free_Stub;
		  pHRDir->realloc = &Cpp_realloc_Stub;
		  pHRDir->terminate = &Cpp_terminate_Stub;
		  pHRDir->flags = hrfOther;

		  pHRDir->allocated = 1;
		}
		else {
		  pHRDir = NULL;
		}
	  }
	}
	else
	{
	  if (BorlandMM_Module == ThisModule)
	  {
		IsBorlandMMDLL = true;
		//Try hook heap redirector of RTL modules
		EnumModules(TryHookRTLHeapRedirector, NULL);
	  }
	}
	//#endif //!_RTLDLL

    pCppDebugHook = PInteger(GetProcAddress(MainModule, CPPdebugHookExport));
    if (!pCppDebugHook)
    {
      pCppDebugHook = &__CPPdebugHook;
    }  
    #ifdef CheckCppObjectTypeEnabled
    GetCppVirtObjSizeByTypeIdPtrFunc =
      (TGetCppVirtObjSizeByTypeIdPtrFunc)&GetCppVirtualObjectSizeByTypeIdPtr;

    GetCppVirtObjTypeIdPtrFunc =
      (TGetCppVirtObjTypeIdPtrFunc)&GetCppVirtualObjectTypeIdPtr;

    GetCppVirtObjTypeNameFunc =
      (TGetCppVirtObjTypeNameFunc)&GetCppVirtualObjectTypeName;

    GetCppVirtObjTypeNameByTypeIdPtrFunc =
      (TGetCppVirtObjTypeNameByTypeIdPtrFunc)&GetCppVirtualObjectTypeNameByTypeIdPtr;

    GetCppVirtObjTypeNameByVTablePtrFunc =
      (TGetCppVirtObjTypeNameByVTablePtrFunc)&GetCppVirtualObjectTypeNameByVTablePtr;
    #endif
     
    IsInDLL = (MainModule != ThisModule);
    if (!IsInDLL)
    {
      if (Patch_terminate())
      {
		terminatePatched = true;
		
        #ifdef EnableMemoryLeakReporting
          #if __BORLANDC__ >= 0x582
          //>= BDS2006 ?
          //"ios.cpp", line 136, ios_base::_Init(), "locale" leaks
		  RegisterExpectedMemoryLeak(20, 8);
		  //"locale0.cpp", line 167, locale::_Init(), "_Locimp" leak due to above leaks
          RegisterExpectedMemoryLeak(68, 1);
          #endif
        #endif
      }
    }
	#ifndef _RTLDLL
	else
	{
	#ifdef EnableMemoryLeakReporting
	  #if __BORLANDC__ >= 0x582
	  //>= BDS2006 ?
	  //"ios.cpp", line 136, ios_base::_Init(), "locale" leaks
	  RegisterExpectedMemoryLeak(20, 8);
	  //"locale0.cpp", line 167, locale::_Init(), "_Locimp" leak due to above leaks
	  RegisterExpectedMemoryLeak(68, 1);

	  RegisterExpectedMemoryLeak(228, 1);
	  #endif
	#endif
	}
	#endif //_RTLDLL
	
	#endif //PatchBCBTerminate
  }
//#endif  
}
#pragma startup BCBInstallFastMM 0

#ifdef PatchBCBTerminate

void BCBUninstallFastMM()
{
  //Sadly we cannot uninstall here since there are still live pointers.
//#if ((!defined(_NO_VCL)) && defined(__DLL__) && defined(_RTLDLL))

//#else
  if (IsMMInstalled && (!terminatePatched))
  {
    //Delphi MemoryManager already installed here
    FinalizeMemoryManager();

    #if __BORLANDC__ >= 0x582
    //>= BDS2006 ?
    System::TMemoryManagerEx AMemoryManager;
    #else
    System::TMemoryManager AMemoryManager;
    #endif
    System::GetMemoryManager(AMemoryManager);

    //MemoryManager uninstalled ?
    bool DelphiMMUninstalled = (AMemoryManager.GetMem != InternalGetMem);
    #ifdef DetectMMOperationsAfterUninstall
    //InvalidMemoryManager get set as Delphi MemoryManager ?
    bool InvalidMMSet = (AMemoryManager.GetMem != StockGetMemPtr);
    #endif
    
    #ifdef CheckCppObjectTypeEnabled
    GetCppVirtObjSizeByTypeIdPtrFunc = NULL;
    GetCppVirtObjTypeIdPtrFunc = NULL;
    GetCppVirtObjTypeNameFunc = NULL;
    GetCppVirtObjTypeNameByTypeIdPtrFunc = NULL;
    GetCppVirtObjTypeNameByVTablePtrFunc = NULL;
    
    FinalizeModuleCodeDataRanges();
    #endif
    
    if (DelphiMMUninstalled)
    {
      if (pHRDir)
      {
        #ifdef DetectMMOperationsAfterUninstall
        if (InvalidMMSet)
        {
          InvalidGetMemPtr = AMemoryManager.GetMem;
          InvalidFreeMemPtr = AMemoryManager.FreeMem;
          InvalidReallocMemPtr = AMemoryManager.ReallocMem;

          pHRDir->malloc = Cpp_Invalid_malloc_Stub;
          pHRDir->free = Cpp_Invalid_free_Stub;
          pHRDir->realloc = Cpp_Invalid_realloc_Stub;
        }
        else
        #endif
          *pHRDir = Old_heap_redirector;
          
        pHRDir = NULL;
      }
	  else
	  {
		if (IsBorlandMMDLL)
		{
		  //Try unhook heap redirector of RTL modules
		#ifdef DetectMMOperationsAfterUninstall
		  EnumModules(TryUnhookRTLHeapRedirector, (void *)InvalidMMSet);
		#else
		  EnumModules(TryUnhookRTLHeapRedirector, NULL);
		#endif
		  FinalizeHeapRedirectorStoreList();
		}
	  }
	}

	#if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
	CallOldFullDebugModeDllEntry();
	#endif
  }
//#endif  
}
#pragma exit BCBUninstallFastMM 0

#endif //PatchBCBTerminate

#ifdef __cplusplus
} // extern "C"
#endif

#pragma option pop

//#endif //!_NO_VCL 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -