leak_check.h (5517B)
1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: leak_check.h 17 // ----------------------------------------------------------------------------- 18 // 19 // This file contains functions that affect leak checking behavior within 20 // targets built with the LeakSanitizer (LSan), a memory leak detector that is 21 // integrated within the AddressSanitizer (ASan) as an additional component, or 22 // which can be used standalone. LSan and ASan are included (or can be provided) 23 // as additional components for most compilers such as Clang, gcc and MSVC. 24 // Note: this leak checking API is not yet supported in MSVC. 25 // Leak checking is enabled by default in all ASan builds. 26 // 27 // https://clang.llvm.org/docs/LeakSanitizer.html 28 // https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer 29 // 30 // GCC and Clang both automatically enable LeakSanitizer when AddressSanitizer 31 // is enabled. To use the mode, simply pass `-fsanitize=address` to both the 32 // compiler and linker. An example Bazel command could be 33 // 34 // $ bazel test --copt=-fsanitize=address --linkopt=-fsanitize=address ... 35 // 36 // GCC and Clang auto support a standalone LeakSanitizer mode (a mode which does 37 // not also use AddressSanitizer). To use the mode, simply pass 38 // `-fsanitize=leak` to both the compiler and linker. Since GCC does not 39 // currently provide a way of detecting this mode at compile-time, GCC users 40 // must also pass -DLEAK_SANITIZER to the compiler. An example Bazel command 41 // could be 42 // 43 // $ bazel test --copt=-DLEAK_SANITIZER --copt=-fsanitize=leak 44 // --linkopt=-fsanitize=leak ... 45 // 46 // ----------------------------------------------------------------------------- 47 #ifndef ABSL_DEBUGGING_LEAK_CHECK_H_ 48 #define ABSL_DEBUGGING_LEAK_CHECK_H_ 49 50 #include <cstddef> 51 52 #include "absl/base/config.h" 53 54 namespace absl { 55 ABSL_NAMESPACE_BEGIN 56 57 // HaveLeakSanitizer() 58 // 59 // Returns true if a leak-checking sanitizer (either ASan or standalone LSan) is 60 // currently built into this target. 61 bool HaveLeakSanitizer(); 62 63 // LeakCheckerIsActive() 64 // 65 // Returns true if a leak-checking sanitizer (either ASan or standalone LSan) is 66 // currently built into this target and is turned on. 67 bool LeakCheckerIsActive(); 68 69 // DoIgnoreLeak() 70 // 71 // Implements `IgnoreLeak()` below. This function should usually 72 // not be called directly; calling `IgnoreLeak()` is preferred. 73 void DoIgnoreLeak(const void* ptr); 74 75 // IgnoreLeak() 76 // 77 // Instruct the leak sanitizer to ignore leak warnings on the object referenced 78 // by the passed pointer, as well as all heap objects transitively referenced 79 // by it. The passed object pointer can point to either the beginning of the 80 // object or anywhere within it. 81 // 82 // Example: 83 // 84 // static T* obj = IgnoreLeak(new T(...)); 85 // 86 // If the passed `ptr` does not point to an actively allocated object at the 87 // time `IgnoreLeak()` is called, the call is a no-op; if it is actively 88 // allocated, leak sanitizer will assume this object is referenced even if 89 // there is no actual reference in user memory. 90 // 91 template <typename T> 92 T* IgnoreLeak(T* ptr) { 93 DoIgnoreLeak(ptr); 94 return ptr; 95 } 96 97 // FindAndReportLeaks() 98 // 99 // If any leaks are detected, prints a leak report and returns true. This 100 // function may be called repeatedly, and does not affect end-of-process leak 101 // checking. 102 // 103 // Example: 104 // if (FindAndReportLeaks()) { 105 // ... diagnostic already printed. Exit with failure code. 106 // exit(1) 107 // } 108 bool FindAndReportLeaks(); 109 110 // LeakCheckDisabler 111 // 112 // This helper class indicates that any heap allocations done in the code block 113 // covered by the scoped object, which should be allocated on the stack, will 114 // not be reported as leaks. Leak check disabling will occur within the code 115 // block and any nested function calls within the code block. 116 // 117 // Example: 118 // 119 // void Foo() { 120 // LeakCheckDisabler disabler; 121 // ... code that allocates objects whose leaks should be ignored ... 122 // } 123 // 124 // REQUIRES: Destructor runs in same thread as constructor 125 class LeakCheckDisabler { 126 public: 127 LeakCheckDisabler(); 128 LeakCheckDisabler(const LeakCheckDisabler&) = delete; 129 LeakCheckDisabler& operator=(const LeakCheckDisabler&) = delete; 130 ~LeakCheckDisabler(); 131 }; 132 133 // RegisterLivePointers() 134 // 135 // Registers `ptr[0,size-1]` as pointers to memory that is still actively being 136 // referenced and for which leak checking should be ignored. This function is 137 // useful if you store pointers in mapped memory, for memory ranges that we know 138 // are correct but for which normal analysis would flag as leaked code. 139 void RegisterLivePointers(const void* ptr, size_t size); 140 141 // UnRegisterLivePointers() 142 // 143 // Deregisters the pointers previously marked as active in 144 // `RegisterLivePointers()`, enabling leak checking of those pointers. 145 void UnRegisterLivePointers(const void* ptr, size_t size); 146 147 ABSL_NAMESPACE_END 148 } // namespace absl 149 150 #endif // ABSL_DEBUGGING_LEAK_CHECK_H_