fork

Fork of cpputest by Rohit Grover

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MemoryLeakDetector.h Source File

MemoryLeakDetector.h

00001 /*
00002  * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of the <organization> nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
00017  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00028 #ifndef D_MemoryLeakDetector_h
00029 #define D_MemoryLeakDetector_h
00030 
00031 enum MemLeakPeriod
00032 {
00033     mem_leak_period_all,
00034     mem_leak_period_disabled,
00035     mem_leak_period_enabled,
00036     mem_leak_period_checking
00037 };
00038 
00039 class TestMemoryAllocator;
00040 
00041 class MemoryLeakFailure
00042 {
00043 public:
00044     virtual ~MemoryLeakFailure()
00045     {
00046     }
00047 
00048     virtual void fail(char* fail_string)=0;
00049 };
00050 
00051 struct SimpleStringBuffer
00052 {
00053     enum
00054     {
00055         SIMPLE_STRING_BUFFER_LEN = 4096
00056     };
00057 
00058     SimpleStringBuffer();
00059     void clear();
00060     void add(const char* format, ...) __check_format__(printf, 2, 3);
00061     char* toString();
00062 
00063     void setWriteLimit(size_t write_limit);
00064     void resetWriteLimit();
00065     bool reachedItsCapacity();
00066 private:
00067     char buffer_[SIMPLE_STRING_BUFFER_LEN];
00068     size_t positions_filled_;
00069     size_t write_limit_;
00070 };
00071 
00072 struct MemoryLeakDetectorNode;
00073 
00074 class MemoryLeakOutputStringBuffer
00075 {
00076 public:
00077     MemoryLeakOutputStringBuffer();
00078 
00079     void clear();
00080 
00081     void startMemoryLeakReporting();
00082     void stopMemoryLeakReporting();
00083 
00084     void reportMemoryLeak(MemoryLeakDetectorNode* leak);
00085 
00086     void reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
00087     void reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
00088     void reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
00089     char* toString();
00090 
00091 private:
00092     void addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator);
00093     void addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator);
00094 
00095     void addMemoryLeakHeader();
00096     void addMemoryLeakFooter(int totalAmountOfLeaks);
00097     void addWarningForUsingMalloc();
00098     void addNoMemoryLeaksMessage();
00099     void addErrorMessageForTooMuchLeaks();
00100 
00101 private:
00102 
00103     int total_leaks_;
00104     bool giveWarningOnUsingMalloc_;
00105 
00106     void reportFailure(const char* message, const char* allocFile,
00107             int allocLine, size_t allocSize,
00108             TestMemoryAllocator* allocAllocator, const char* freeFile,
00109             int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter);
00110 
00111     SimpleStringBuffer outputBuffer_;
00112 };
00113 
00114 struct MemoryLeakDetectorNode
00115 {
00116     MemoryLeakDetectorNode() :
00117         size_(0), number_(0), memory_(0), file_(0), line_(0), allocator_(0), period_(mem_leak_period_enabled), next_(0)
00118     {
00119     }
00120 
00121     void init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line);
00122 
00123     size_t size_;
00124     unsigned number_;
00125     char* memory_;
00126     const char* file_;
00127     int line_;
00128     TestMemoryAllocator* allocator_;
00129     MemLeakPeriod period_;
00130 
00131 private:
00132     friend struct MemoryLeakDetectorList;
00133     MemoryLeakDetectorNode* next_;
00134 };
00135 
00136 struct MemoryLeakDetectorList
00137 {
00138     MemoryLeakDetectorList() :
00139         head_(0)
00140     {}
00141 
00142     void addNewNode(MemoryLeakDetectorNode* node);
00143     MemoryLeakDetectorNode* retrieveNode(char* memory);
00144     MemoryLeakDetectorNode* removeNode(char* memory);
00145 
00146     MemoryLeakDetectorNode* getFirstLeak(MemLeakPeriod period);
00147     MemoryLeakDetectorNode* getNextLeak(MemoryLeakDetectorNode* node,
00148             MemLeakPeriod period);
00149     MemoryLeakDetectorNode* getLeakFrom(MemoryLeakDetectorNode* node,
00150             MemLeakPeriod period);
00151 
00152     int getTotalLeaks(MemLeakPeriod period);
00153     bool hasLeaks(MemLeakPeriod period);
00154     void clearAllAccounting(MemLeakPeriod period);
00155 
00156     bool isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period);
00157 
00158 private:
00159     MemoryLeakDetectorNode* head_;
00160 };
00161 
00162 struct MemoryLeakDetectorTable
00163 {
00164     void clearAllAccounting(MemLeakPeriod period);
00165 
00166     void addNewNode(MemoryLeakDetectorNode* node);
00167     MemoryLeakDetectorNode* retrieveNode(char* memory);
00168     MemoryLeakDetectorNode* removeNode(char* memory);
00169 
00170     bool hasLeaks(MemLeakPeriod period);
00171     int getTotalLeaks(MemLeakPeriod period);
00172 
00173     MemoryLeakDetectorNode* getFirstLeak(MemLeakPeriod period);
00174     MemoryLeakDetectorNode* getNextLeak(MemoryLeakDetectorNode* leak,
00175             MemLeakPeriod period);
00176 
00177 private:
00178     unsigned long hash(char* memory);
00179 
00180     enum
00181     {
00182         hash_prime = MEMORY_LEAK_HASH_TABLE_SIZE
00183     };
00184     MemoryLeakDetectorList table_[hash_prime];
00185 };
00186 
00187 class MemoryLeakDetector
00188 {
00189 public:
00190     MemoryLeakDetector(MemoryLeakFailure* reporter);
00191     virtual ~MemoryLeakDetector()
00192     {
00193     }
00194 
00195     void enable();
00196     void disable();
00197 
00198     void disableAllocationTypeChecking();
00199     void enableAllocationTypeChecking();
00200 
00201     void startChecking();
00202     void stopChecking();
00203 
00204     const char* report(MemLeakPeriod period);
00205     void markCheckingPeriodLeaksAsNonCheckingPeriod();
00206     int totalMemoryLeaks(MemLeakPeriod period);
00207     void clearAllAccounting(MemLeakPeriod period);
00208 
00209     char* allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately = false);
00210     char* allocMemory(TestMemoryAllocator* allocator, size_t size,
00211             const char* file, int line, bool allocatNodesSeperately = false);
00212     void deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately = false);
00213     void deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately = false);
00214     char* reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately = false);
00215 
00216     void invalidateMemory(char* memory);
00217     void removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately);
00218     enum
00219     {
00220         memory_corruption_buffer_size = 3
00221     };
00222 
00223     unsigned getCurrentAllocationNumber();
00224 private:
00225     MemoryLeakFailure* reporter_;
00226     MemLeakPeriod current_period_;
00227     MemoryLeakOutputStringBuffer outputBuffer_;
00228     MemoryLeakDetectorTable memoryTable_;
00229     bool doAllocationTypeChecking_;
00230     unsigned allocationSequenceNumber_;
00231 
00232     char* allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately);
00233     char* reallocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately);
00234     MemoryLeakDetectorNode* createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately);
00235 
00236 
00237     bool validMemoryCorruptionInformation(char* memory);
00238     bool matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator);
00239 
00240     void storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line);
00241     void ConstructMemoryLeakReport(MemLeakPeriod period);
00242 
00243     size_t sizeOfMemoryWithCorruptionInfo(size_t size);
00244     MemoryLeakDetectorNode* getNodeFromMemoryPointer(char* memory, size_t size);
00245 
00246     char* reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately);
00247 
00248     void addMemoryCorruptionInformation(char* memory);
00249     void checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately);
00250 };
00251 
00252 #endif