diff --git a/include/trick/MemoryManager.hh b/include/trick/MemoryManager.hh index dd63b3cc..09477362 100644 --- a/include/trick/MemoryManager.hh +++ b/include/trick/MemoryManager.hh @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -683,6 +684,8 @@ namespace Trick { std::vector dependencies; /**< ** list of allocations used in a checkpoint. */ std::vector stl_dependencies; /**< ** list of allocations known to be STL checkpoint allocations */ + bool resetting_memory; + std::list deleted_addr_list; /**< ** list of addresses that have been deleted during reset_memory(). */ void execute_checkpoint( std::ostream& out_s ); diff --git a/trick_source/sim_services/MemoryManager/MemoryManager.cpp b/trick_source/sim_services/MemoryManager/MemoryManager.cpp index 3326d82d..a4dc37df 100644 --- a/trick_source/sim_services/MemoryManager/MemoryManager.cpp +++ b/trick_source/sim_services/MemoryManager/MemoryManager.cpp @@ -23,6 +23,7 @@ Trick::MemoryManager::MemoryManager() debug_level = 0; hexfloat_checkpoint = 0; reduced_checkpoint = 1; + resetting_memory = false; expanded_arrays = 0; // start counter at 100mil. This (hopefully) ensures all alloc'ed ids are after external variables. alloc_info_map_counter = 100000000 ; diff --git a/trick_source/sim_services/MemoryManager/MemoryManager_clear_memory.cpp b/trick_source/sim_services/MemoryManager/MemoryManager_clear_memory.cpp index 46e17d36..20f0fc1b 100644 --- a/trick_source/sim_services/MemoryManager/MemoryManager_clear_memory.cpp +++ b/trick_source/sim_services/MemoryManager/MemoryManager_clear_memory.cpp @@ -295,6 +295,11 @@ void Trick::MemoryManager::reset_memory() { std::vector deletion_list; int ii, n_addrs; + // Clear the deleted_addr_list at the start of reset memory. As delete_var() is called, + // and resetting_memory == true, the deleted address will be added to the deleted_addr_list. + resetting_memory = true; + deleted_addr_list.clear(); + pthread_mutex_lock(&mm_mutex); for (pos=alloc_info_map.begin() ; pos!=alloc_info_map.end() ; pos++ ) { alloc_info = pos->second; @@ -310,6 +315,9 @@ void Trick::MemoryManager::reset_memory() { delete_var( deletion_list[ii]); } + resetting_memory = false; + deleted_addr_list.clear(); + // reset counter to 100mil. This (hopefully) ensures all alloc'ed ids are after external variables. alloc_info_map_counter = 100000000 ; } diff --git a/trick_source/sim_services/MemoryManager/MemoryManager_delete_var.cpp b/trick_source/sim_services/MemoryManager/MemoryManager_delete_var.cpp index 0c72f71d..a68630df 100644 --- a/trick_source/sim_services/MemoryManager/MemoryManager_delete_var.cpp +++ b/trick_source/sim_services/MemoryManager/MemoryManager_delete_var.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include "trick/MemoryManager.hh" @@ -38,6 +39,14 @@ int Trick::MemoryManager::delete_var(void* address ) { if ( alloc_info->stcl == TRICK_LOCAL ) { if ( alloc_info->alloc_type == TRICK_ALLOC_MALLOC ) { io_src_destruct_class( alloc_info ); + + // The destructor that we just called MAY have deleted addresses + // that are already planned for deletion, say during reset_memory. + // So, keep a record of what we've recently deleted so we don't + // to warn that we can't find it, when reset_memory also tries to + // delete that same address. + deleted_addr_list.push_back(address); + free( address); } else if ( alloc_info->alloc_type == TRICK_ALLOC_NEW ) { io_src_delete_class( alloc_info ); @@ -64,10 +73,33 @@ int Trick::MemoryManager::delete_var(void* address ) { free(alloc_info); } else { - std::stringstream message; - message << "The MemoryManager cannot delete memory at address [" - << address << "] because it has no record of it."; - emitWarning(message.str()); + + // The allocation (address) we're tring to delete may have just been + // deleted by a user's destructor (using delete_var). Check the deleted_addr_list + // to see if the allocation was just deleted. If it was, then there's no + // problem. If it wasn't, then the MemoryManager never knew about it, and + // this call to delete_var() is a problem. + + if ( resetting_memory == true) { + // Check the deleted_addr_list to see whether we recently deleted this address. + std::list::iterator iter = + std::find( deleted_addr_list.begin(), deleted_addr_list.end(), address ); + // If we didn't recently delete it, then there's a problem. + if ( iter == deleted_addr_list.end() ) { + std::stringstream message; + message << "The MemoryManager cannot delete memory at address [" + << address << "] because it has no record of it. Furthermore," + << " the MemoryManager has not recently deleted it while" + << " resetting memory for a checkpoint reload."; + emitWarning(message.str()); + } + } else { + std::stringstream message; + message << "The MemoryManager cannot delete memory at address [" + << address << "] because it has no record of it."; + emitWarning(message.str()); + } + return 1 ; } diff --git a/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp b/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp index c4a1e86a..afdced79 100644 --- a/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp +++ b/trick_source/sim_services/MemoryManager/MemoryManager_restore.cpp @@ -21,6 +21,7 @@ int Trick::MemoryManager::read_checkpoint( std::istream *is, bool do_restore_stl emitError("Checkpoint restore failed.") ; } + // Search for stls and restore them if(do_restore_stls) { for ( pos=alloc_info_map.begin() ; pos!=alloc_info_map.end() ; pos++ ) { @@ -102,6 +103,11 @@ int Trick::MemoryManager::init_from_checkpoint( std::istream *is) { reset_memory(); + if (debug_level) { + std::cout << std::endl << "- Reading checkpoint." << std::endl; + std::cout.flush(); + } + read_checkpoint( is); if (debug_level) {