Merge pull request #1142 from scottslacksmith/master
Fix/silence false positive memory leaks reported by Microsoft's debug CRT
This commit is contained in:
		@@ -294,6 +294,43 @@ void Mutex::AssertHeld() {
 | 
				
			|||||||
      << "The current thread is not holding the mutex @" << this;
 | 
					      << "The current thread is not holding the mutex @" << this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Use the RAII idiom to flag mem allocs that are intentionally never
 | 
				
			||||||
 | 
					// deallocated. The motivation is to silence the false positive mem leaks
 | 
				
			||||||
 | 
					// that are reported by the debug version of MS's CRT which can only detect
 | 
				
			||||||
 | 
					// if an alloc is missing a matching deallocation.
 | 
				
			||||||
 | 
					// Example:
 | 
				
			||||||
 | 
					//    MemoryIsNotDeallocated memory_is_not_deallocated;
 | 
				
			||||||
 | 
					//    critical_section_ = new CRITICAL_SECTION;
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					class MemoryIsNotDeallocated
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  MemoryIsNotDeallocated() : old_crtdbg_flag_(0) {
 | 
				
			||||||
 | 
					#ifdef _MSC_VER
 | 
				
			||||||
 | 
					    old_crtdbg_flag_ = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
 | 
				
			||||||
 | 
					    // Set heap allocation block type to _IGNORE_BLOCK so that MS debug CRT
 | 
				
			||||||
 | 
					    // doesn't report mem leak if there's no matching deallocation.
 | 
				
			||||||
 | 
					    _CrtSetDbgFlag(old_crtdbg_flag_ & ~_CRTDBG_ALLOC_MEM_DF);
 | 
				
			||||||
 | 
					#endif  //  _MSC_VER
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ~MemoryIsNotDeallocated() {
 | 
				
			||||||
 | 
					#ifdef _MSC_VER
 | 
				
			||||||
 | 
					    // Restore the original _CRTDBG_ALLOC_MEM_DF flag
 | 
				
			||||||
 | 
					    _CrtSetDbgFlag(old_crtdbg_flag_);
 | 
				
			||||||
 | 
					#endif  //  _MSC_VER
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 private:
 | 
				
			||||||
 | 
					  int old_crtdbg_flag_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GTEST_DISALLOW_COPY_AND_ASSIGN_(MemoryIsNotDeallocated);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Initializes owner_thread_id_ and critical_section_ in static mutexes.
 | 
					// Initializes owner_thread_id_ and critical_section_ in static mutexes.
 | 
				
			||||||
void Mutex::ThreadSafeLazyInit() {
 | 
					void Mutex::ThreadSafeLazyInit() {
 | 
				
			||||||
  // Dynamic mutexes are initialized in the constructor.
 | 
					  // Dynamic mutexes are initialized in the constructor.
 | 
				
			||||||
@@ -304,7 +341,11 @@ void Mutex::ThreadSafeLazyInit() {
 | 
				
			|||||||
        // If critical_section_init_phase_ was 0 before the exchange, we
 | 
					        // If critical_section_init_phase_ was 0 before the exchange, we
 | 
				
			||||||
        // are the first to test it and need to perform the initialization.
 | 
					        // are the first to test it and need to perform the initialization.
 | 
				
			||||||
        owner_thread_id_ = 0;
 | 
					        owner_thread_id_ = 0;
 | 
				
			||||||
        critical_section_ = new CRITICAL_SECTION;
 | 
					        {
 | 
				
			||||||
 | 
					          // Use RAII to flag that following mem alloc is never deallocated.
 | 
				
			||||||
 | 
					          MemoryIsNotDeallocated memory_is_not_deallocated;
 | 
				
			||||||
 | 
					          critical_section_ = new CRITICAL_SECTION;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        ::InitializeCriticalSection(critical_section_);
 | 
					        ::InitializeCriticalSection(critical_section_);
 | 
				
			||||||
        // Updates the critical_section_init_phase_ to 2 to signal
 | 
					        // Updates the critical_section_init_phase_ to 2 to signal
 | 
				
			||||||
        // initialization complete.
 | 
					        // initialization complete.
 | 
				
			||||||
@@ -546,7 +587,8 @@ class ThreadLocalRegistryImpl {
 | 
				
			|||||||
  // Returns map of thread local instances.
 | 
					  // Returns map of thread local instances.
 | 
				
			||||||
  static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
 | 
					  static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
 | 
				
			||||||
    mutex_.AssertHeld();
 | 
					    mutex_.AssertHeld();
 | 
				
			||||||
    static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals;
 | 
					    MemoryIsNotDeallocated memory_is_not_deallocated;
 | 
				
			||||||
 | 
					    static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals();
 | 
				
			||||||
    return map;
 | 
					    return map;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user