#include "munga.h" #pragma hdrstop #include "plug.h" #include "node.h" #include "hash.h" class MemoryRegister; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MRStats ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define MR_FILENAME_LEN (64) #define MR_HASH_SIZE (500) class MRStats: public Plug { friend class MemoryRegister; public: MRStats( void *address, MRStatsAddressType address_type, char *fileName, int lineNum ); ~MRStats(); private: void *address; char fileName[MR_FILENAME_LEN]; int lineNum; #ifdef MEMORY_VERIFY MRStatsAddressType addressType; #endif }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryRegister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class MemoryRegister: public Node { public: friend void Start_Registering_Function(); friend void Stop_Registering_Function(); friend void Register_Pointer_Function( void *address, MRStatsAddressType address_type, char *file_name, int line_num ); friend void Unregister_Pointer_Function( void *address, char *file_name, int line_num ); friend void Address_Registration_Function( void *address, char *file_name, int line_num ); friend void Check_All_Signatures_Function( char *file_name, int line_num ); MemoryRegister(); ~MemoryRegister(); Logical TestInstance() const; void Report(); private: Logical RegisterAddress( void *address, MRStatsAddressType, char *fileName, int lineNum ); Logical ReleaseAddress( void *address, char *fileName, int lineNum ); Logical IsRegistered( void *address ); void AddressRegistration( void *address, char *file_name, int line_num ); void CheckAllSignatures( char *file_name, int line_num ); static Logical VerifyAddress( void *address, char *fileName, int lineNum ); private: HashOf memoryStats; Logical collectStats; long registrations; #ifdef MEMORY_VERIFY Logical checkAllSignatures; ChainOf verificationSocket; Time nextTell; #endif }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryRegisterShell ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class MemoryRegisterShell { public: MemoryRegisterShell(); ~MemoryRegisterShell(); static MemoryRegister *store; }; #ifdef MEMORY_REGISTER MemoryRegisterShell memory_register_shell; #endif MemoryRegister *MemoryRegisterShell::store=NULL; // //########################################################################### // MemoryRegisterShell //########################################################################### // MemoryRegisterShell::MemoryRegisterShell() { store = new MemoryRegister; Check(store); } // //########################################################################### // ~MemoryRegisterShell //########################################################################### // MemoryRegisterShell::~MemoryRegisterShell() { MemoryRegister *obj; Check(store); store->Report(); obj = store; store = NULL; delete obj; } // //########################################################################### // MRStats //########################################################################### // #ifdef MEMORY_VERIFY MRStats::MRStats( void *address, MRStatsAddressType address_type, char *fileName, int lineNum ) { this->address = address; this->lineNum = lineNum; Str_Copy(this->fileName, fileName, MR_FILENAME_LEN); this->addressType = address_type; } #else MRStats::MRStats( void *address, MRStatsAddressType, char *fileName, int lineNum ) { this->address = address; this->lineNum = lineNum; Str_Copy(this->fileName, fileName, MR_FILENAME_LEN); } #endif MRStats::~MRStats() { } // //########################################################################### // MemoryRegister //########################################################################### // #ifdef MEMORY_VERIFY MemoryRegister::MemoryRegister(): memoryStats(MR_HASH_SIZE, NULL, True), verificationSocket(NULL) { collectStats = True; registrations = 0; checkAllSignatures = True; nextTell = Now(); } #else MemoryRegister::MemoryRegister(): memoryStats(MR_HASH_SIZE, NULL, True) { collectStats = True; registrations = 0; } #endif // //########################################################################### // ~MemoryRegister //########################################################################### // MemoryRegister::~MemoryRegister() { } // //########################################################################### // TestInstance //########################################################################### // Logical MemoryRegister::TestInstance() const { Node::TestInstance(); Check(&memoryStats); #ifdef MEMORY_VERIFY Check(&verificationSocket); #endif return True; } // //########################################################################### // RegisterAddress //########################################################################### // Logical MemoryRegister::RegisterAddress( void *address, MRStatsAddressType address_type, char *fileName, int lineNum ) { MRStats *stats; if (!collectStats) return True; if (!VerifyAddress(address, fileName, lineNum)) return False; Check(&memoryStats); if ((stats = memoryStats.Find((unsigned long)address)) != NULL) { Tell( stats->address << " : " << stats->fileName << '(' << stats->lineNum << ")\n" ); Verify_Failed( "MemoryRegister::RegisterAddress: Address already registered by above", fileName, lineNum ); return False; } stats = new MRStats(address, address_type, fileName, lineNum); Check(stats); Check(&memoryStats); collectStats = False; memoryStats.AddValue(stats, (unsigned long)address); #ifdef MEMORY_VERIFY // Currently, only verify signatured objects if (address_type == ObjectMRStatsAddressType) { Check(&verificationSocket); checkAllSignatures = False; verificationSocket.Add(stats); checkAllSignatures = True; } #endif collectStats = True; registrations++; return True; } // //########################################################################### // ReleaseAddress //########################################################################### // Logical MemoryRegister::ReleaseAddress( void *address, char *fileName, int lineNum ) { MRStats *stats; if (!collectStats) return True; if (!VerifyAddress(address, fileName, lineNum)) return False; stats = memoryStats.Find((unsigned long)address); if (stats != NULL) { Check(stats); collectStats = False; delete stats; collectStats = True; return True; } Verify_Failed( "MemoryRegister::ReleaseAddress: Address not found", fileName, lineNum ); return False; } // //########################################################################### // IsRegistered //########################################################################### // Logical MemoryRegister::IsRegistered(void *address) { return (memoryStats.Find((unsigned long)address) != NULL); } // //########################################################################### // AddressRegistration //########################################################################### // void MemoryRegister::AddressRegistration( void *address, char *file_name, int line_num ) { MRStats *stats; if ((stats = memoryStats.Find((unsigned long)address)) != NULL) { std::cout << stats->address << " : allocated at : " << stats->fileName << '(' << stats->lineNum << ")\n" ; } else { Verify_Failed( "MemoryRegister::AddressRegistration: Address not found", file_name, line_num ); } } // //########################################################################### // CheckAllSignatures //########################################################################### // #ifdef MEMORY_VERIFY void MemoryRegister::CheckAllSignatures( char *file_name, int line_num ) { if (checkAllSignatures) { checkAllSignatures = False; if (nextTell < Now()) { nextTell += 1.0f; Tell("."); } ChainIteratorOf iterator(&verificationSocket); MRStats *stats; Check(&iterator); while ((stats = iterator.ReadAndNext()) != NULL) { Check(stats); switch (stats->addressType) { case PointerMRStatsAddressType: Check_Pointer(stats->address); break; case ObjectMRStatsAddressType: if (Is_Signature_Bad((Signature*)stats->address)) { Tell( stats->address << " : allocated at : " << stats->fileName << '(' << stats->lineNum << ") corrupted at : " << file_name << '(' << line_num << ")\n" ); Check_Signature((Signature*)stats->address); } break; default: Fail("MemoryRegister::CheckAllSignatures - Unknown addressType"); break; } } checkAllSignatures = True; } } #else void MemoryRegister::CheckAllSignatures( char*, int ) { } #endif // //########################################################################### // Report //########################################################################### // void MemoryRegister::Report() { HashIteratorOf iterator(memoryStats); MRStats *stats; Tell("MemoryRegister::Report\n"); Tell("Registrations " << registrations << std::endl); Tell("Unreleased Addresses:\n"); while ((stats = iterator.ReadAndNext()) != NULL) { Check(stats); std::cout << stats->address << " : " << stats->fileName << '(' << stats->lineNum << ")\n" ; } } // //########################################################################### // VerifyAddress //########################################################################### // Logical MemoryRegister::VerifyAddress( void *address, char *fileName, int lineNum ) { // // HACK - An improvement would make sure that the memory // address is within our heap or stack // if (address == 0L) { Verify_Failed( "MemoryRegister::VerifyAddress: Address is NULL", fileName, lineNum ); return False; } return True; } // //########################################################################### // Start //########################################################################### // void Start_Registering_Function() { #if 0 MemoryRegister::store = new MemoryRegister; Check(MemoryRegister::store); #endif } // //########################################################################### // Stop //########################################################################### // void Stop_Registering_Function() { #if 0 MemoryRegister *obj; Check(MemoryRegister::store); MemoryRegister::store->Report(); obj = MemoryRegister::store; MemoryRegister::store = NULL; delete obj; #endif } // //########################################################################### // Register_Pointer_Function //########################################################################### // void Register_Pointer_Function( void *address, MRStatsAddressType address_type, char *file_name, int line_num ) { if (MemoryRegisterShell::store) { MemoryRegisterShell::store->RegisterAddress( address, address_type, file_name, line_num ); } } // //########################################################################### // Unregister_Pointer_Function //########################################################################### // void Unregister_Pointer_Function( void *address, char *file_name, int line_num ) { if (MemoryRegisterShell::store) { MemoryRegisterShell::store->ReleaseAddress(address, file_name, line_num); } } // //########################################################################### // Address_Registration_Function //########################################################################### // void Address_Registration_Function( void *address, char *file_name, int line_num ) { if (MemoryRegisterShell::store) { MemoryRegisterShell::store->AddressRegistration(address, file_name, line_num); } } // //########################################################################### // Check_All_Signatures_Function //########################################################################### // void Check_All_Signatures_Function( char *file_name, int line_num ) { if (MemoryRegisterShell::store) { MemoryRegisterShell::store->CheckAllSignatures(file_name, line_num); } }