fork
Fork of cpputest by
src/CppUTest/MemoryLeakDetector.cpp@3:9e8c8907d9ee, 2015-05-13 (annotated)
- Committer:
- Kojto
- Date:
- Wed May 13 13:20:35 2015 +0000
- Revision:
- 3:9e8c8907d9ee
- Parent:
- 1:4769360130ed
Rename console to mbed_cpputest_console (as in mbed testrunner)
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Rohit Grover |
1:4769360130ed | 1 | /* |
Rohit Grover |
1:4769360130ed | 2 | * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde |
Rohit Grover |
1:4769360130ed | 3 | * All rights reserved. |
Rohit Grover |
1:4769360130ed | 4 | * |
Rohit Grover |
1:4769360130ed | 5 | * Redistribution and use in source and binary forms, with or without |
Rohit Grover |
1:4769360130ed | 6 | * modification, are permitted provided that the following conditions are met: |
Rohit Grover |
1:4769360130ed | 7 | * * Redistributions of source code must retain the above copyright |
Rohit Grover |
1:4769360130ed | 8 | * notice, this list of conditions and the following disclaimer. |
Rohit Grover |
1:4769360130ed | 9 | * * Redistributions in binary form must reproduce the above copyright |
Rohit Grover |
1:4769360130ed | 10 | * notice, this list of conditions and the following disclaimer in the |
Rohit Grover |
1:4769360130ed | 11 | * documentation and/or other materials provided with the distribution. |
Rohit Grover |
1:4769360130ed | 12 | * * Neither the name of the <organization> nor the |
Rohit Grover |
1:4769360130ed | 13 | * names of its contributors may be used to endorse or promote products |
Rohit Grover |
1:4769360130ed | 14 | * derived from this software without specific prior written permission. |
Rohit Grover |
1:4769360130ed | 15 | * |
Rohit Grover |
1:4769360130ed | 16 | * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY |
Rohit Grover |
1:4769360130ed | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
Rohit Grover |
1:4769360130ed | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
Rohit Grover |
1:4769360130ed | 19 | * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY |
Rohit Grover |
1:4769360130ed | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
Rohit Grover |
1:4769360130ed | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
Rohit Grover |
1:4769360130ed | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
Rohit Grover |
1:4769360130ed | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
Rohit Grover |
1:4769360130ed | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
Rohit Grover |
1:4769360130ed | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
Rohit Grover |
1:4769360130ed | 26 | */ |
Rohit Grover |
1:4769360130ed | 27 | #include "CppUTest/TestHarness.h" |
Rohit Grover |
1:4769360130ed | 28 | #include "CppUTest/MemoryLeakDetector.h" |
Rohit Grover |
1:4769360130ed | 29 | #include "CppUTest/TestMemoryAllocator.h" |
Rohit Grover |
1:4769360130ed | 30 | #include "CppUTest/PlatformSpecificFunctions.h" |
Rohit Grover |
1:4769360130ed | 31 | |
Rohit Grover |
1:4769360130ed | 32 | #define UNKNOWN ((char*)("<unknown>")) |
Rohit Grover |
1:4769360130ed | 33 | |
Rohit Grover |
1:4769360130ed | 34 | SimpleStringBuffer::SimpleStringBuffer() : |
Rohit Grover |
1:4769360130ed | 35 | positions_filled_(0), write_limit_(SIMPLE_STRING_BUFFER_LEN-1) |
Rohit Grover |
1:4769360130ed | 36 | { |
Rohit Grover |
1:4769360130ed | 37 | } |
Rohit Grover |
1:4769360130ed | 38 | |
Rohit Grover |
1:4769360130ed | 39 | void SimpleStringBuffer::clear() |
Rohit Grover |
1:4769360130ed | 40 | { |
Rohit Grover |
1:4769360130ed | 41 | positions_filled_ = 0; |
Rohit Grover |
1:4769360130ed | 42 | buffer_[0] = '\0'; |
Rohit Grover |
1:4769360130ed | 43 | } |
Rohit Grover |
1:4769360130ed | 44 | |
Rohit Grover |
1:4769360130ed | 45 | void SimpleStringBuffer::add(const char* format, ...) |
Rohit Grover |
1:4769360130ed | 46 | { |
Rohit Grover |
1:4769360130ed | 47 | int count = 0; |
Rohit Grover |
1:4769360130ed | 48 | size_t positions_left = write_limit_ - positions_filled_; |
Rohit Grover |
1:4769360130ed | 49 | if (positions_left <= 0) return; |
Rohit Grover |
1:4769360130ed | 50 | |
Rohit Grover |
1:4769360130ed | 51 | va_list arguments; |
Rohit Grover |
1:4769360130ed | 52 | va_start(arguments, format); |
Rohit Grover |
1:4769360130ed | 53 | count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments); |
Rohit Grover |
1:4769360130ed | 54 | if (count > 0) positions_filled_ += (size_t) count; |
Rohit Grover |
1:4769360130ed | 55 | if (positions_filled_ > write_limit_) positions_filled_ = write_limit_; |
Rohit Grover |
1:4769360130ed | 56 | va_end(arguments); |
Rohit Grover |
1:4769360130ed | 57 | } |
Rohit Grover |
1:4769360130ed | 58 | |
Rohit Grover |
1:4769360130ed | 59 | char* SimpleStringBuffer::toString() |
Rohit Grover |
1:4769360130ed | 60 | { |
Rohit Grover |
1:4769360130ed | 61 | return buffer_; |
Rohit Grover |
1:4769360130ed | 62 | } |
Rohit Grover |
1:4769360130ed | 63 | |
Rohit Grover |
1:4769360130ed | 64 | void SimpleStringBuffer::setWriteLimit(size_t write_limit) |
Rohit Grover |
1:4769360130ed | 65 | { |
Rohit Grover |
1:4769360130ed | 66 | write_limit_ = write_limit; |
Rohit Grover |
1:4769360130ed | 67 | if (write_limit_ > SIMPLE_STRING_BUFFER_LEN-1) |
Rohit Grover |
1:4769360130ed | 68 | write_limit_ = SIMPLE_STRING_BUFFER_LEN-1; |
Rohit Grover |
1:4769360130ed | 69 | } |
Rohit Grover |
1:4769360130ed | 70 | void SimpleStringBuffer::resetWriteLimit() |
Rohit Grover |
1:4769360130ed | 71 | { |
Rohit Grover |
1:4769360130ed | 72 | write_limit_ = SIMPLE_STRING_BUFFER_LEN-1; |
Rohit Grover |
1:4769360130ed | 73 | } |
Rohit Grover |
1:4769360130ed | 74 | |
Rohit Grover |
1:4769360130ed | 75 | bool SimpleStringBuffer::reachedItsCapacity() |
Rohit Grover |
1:4769360130ed | 76 | { |
Rohit Grover |
1:4769360130ed | 77 | return positions_filled_ >= write_limit_; |
Rohit Grover |
1:4769360130ed | 78 | } |
Rohit Grover |
1:4769360130ed | 79 | |
Rohit Grover |
1:4769360130ed | 80 | //////////////////////// |
Rohit Grover |
1:4769360130ed | 81 | |
Rohit Grover |
1:4769360130ed | 82 | #define MEM_LEAK_TOO_MUCH "\netc etc etc etc. !!!! Too much memory leaks to report. Bailing out\n" |
Rohit Grover |
1:4769360130ed | 83 | #define MEM_LEAK_FOOTER "Total number of leaks: " |
Rohit Grover |
1:4769360130ed | 84 | #define MEM_LEAK_ADDITION_MALLOC_WARNING "NOTE:\n" \ |
Rohit Grover |
1:4769360130ed | 85 | "\tMemory leak reports about malloc and free can be caused by allocating using the cpputest version of malloc,\n" \ |
Rohit Grover |
1:4769360130ed | 86 | "\tbut deallocate using the standard free.\n" \ |
Rohit Grover |
1:4769360130ed | 87 | "\tIf this is the case, check whether your malloc/free replacements are working (#define malloc cpputest_malloc etc).\n" |
Rohit Grover |
1:4769360130ed | 88 | |
Rohit Grover |
1:4769360130ed | 89 | MemoryLeakOutputStringBuffer::MemoryLeakOutputStringBuffer() |
Rohit Grover |
1:4769360130ed | 90 | : total_leaks_(0), giveWarningOnUsingMalloc_(false) |
Rohit Grover |
1:4769360130ed | 91 | { |
Rohit Grover |
1:4769360130ed | 92 | } |
Rohit Grover |
1:4769360130ed | 93 | |
Rohit Grover |
1:4769360130ed | 94 | void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator) |
Rohit Grover |
1:4769360130ed | 95 | { |
Rohit Grover |
1:4769360130ed | 96 | outputBuffer_.add(" allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name()); |
Rohit Grover |
1:4769360130ed | 97 | } |
Rohit Grover |
1:4769360130ed | 98 | |
Rohit Grover |
1:4769360130ed | 99 | void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator) |
Rohit Grover |
1:4769360130ed | 100 | { |
Rohit Grover |
1:4769360130ed | 101 | outputBuffer_.add(" deallocated at file: %s line: %d type: %s\n", freeFile, freeLineNumber, allocator->free_name()); |
Rohit Grover |
1:4769360130ed | 102 | } |
Rohit Grover |
1:4769360130ed | 103 | |
Rohit Grover |
1:4769360130ed | 104 | void MemoryLeakOutputStringBuffer::addNoMemoryLeaksMessage() |
Rohit Grover |
1:4769360130ed | 105 | { |
Rohit Grover |
1:4769360130ed | 106 | outputBuffer_.add("No memory leaks were detected."); |
Rohit Grover |
1:4769360130ed | 107 | } |
Rohit Grover |
1:4769360130ed | 108 | |
Rohit Grover |
1:4769360130ed | 109 | void MemoryLeakOutputStringBuffer::startMemoryLeakReporting() |
Rohit Grover |
1:4769360130ed | 110 | { |
Rohit Grover |
1:4769360130ed | 111 | giveWarningOnUsingMalloc_ = false; |
Rohit Grover |
1:4769360130ed | 112 | total_leaks_ = 0; |
Rohit Grover |
1:4769360130ed | 113 | |
Rohit Grover |
1:4769360130ed | 114 | size_t memory_leak_normal_footer_size = sizeof(MEM_LEAK_FOOTER) + 10 + sizeof(MEM_LEAK_TOO_MUCH); /* the number of leaks */ |
Rohit Grover |
1:4769360130ed | 115 | size_t memory_leak_foot_size_with_malloc_warning = memory_leak_normal_footer_size + sizeof(MEM_LEAK_ADDITION_MALLOC_WARNING); |
Rohit Grover |
1:4769360130ed | 116 | |
Rohit Grover |
1:4769360130ed | 117 | outputBuffer_.setWriteLimit(SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN - memory_leak_foot_size_with_malloc_warning); |
Rohit Grover |
1:4769360130ed | 118 | } |
Rohit Grover |
1:4769360130ed | 119 | |
Rohit Grover |
1:4769360130ed | 120 | void MemoryLeakOutputStringBuffer::reportMemoryLeak(MemoryLeakDetectorNode* leak) |
Rohit Grover |
1:4769360130ed | 121 | { |
Rohit Grover |
1:4769360130ed | 122 | if (total_leaks_ == 0) { |
Rohit Grover |
1:4769360130ed | 123 | addMemoryLeakHeader(); |
Rohit Grover |
1:4769360130ed | 124 | } |
Rohit Grover |
1:4769360130ed | 125 | |
Rohit Grover |
1:4769360130ed | 126 | total_leaks_++; |
Rohit Grover |
1:4769360130ed | 127 | outputBuffer_.add("Alloc num (%u) Leak size: %lu Allocated at: %s and line: %d. Type: \"%s\"\n\t Memory: <%p> Content: \"%.15s\"\n", |
Rohit Grover |
1:4769360130ed | 128 | leak->number_, (unsigned long) leak->size_, leak->file_, leak->line_, leak->allocator_->alloc_name(), leak->memory_, leak->memory_); |
Rohit Grover |
1:4769360130ed | 129 | |
Rohit Grover |
1:4769360130ed | 130 | if (PlatformSpecificStrCmp(leak->allocator_->alloc_name(), "malloc") == 0) |
Rohit Grover |
1:4769360130ed | 131 | giveWarningOnUsingMalloc_ = true; |
Rohit Grover |
1:4769360130ed | 132 | } |
Rohit Grover |
1:4769360130ed | 133 | |
Rohit Grover |
1:4769360130ed | 134 | void MemoryLeakOutputStringBuffer::stopMemoryLeakReporting() |
Rohit Grover |
1:4769360130ed | 135 | { |
Rohit Grover |
1:4769360130ed | 136 | if (total_leaks_ == 0) { |
Rohit Grover |
1:4769360130ed | 137 | addNoMemoryLeaksMessage(); |
Rohit Grover |
1:4769360130ed | 138 | return; |
Rohit Grover |
1:4769360130ed | 139 | } |
Rohit Grover |
1:4769360130ed | 140 | |
Rohit Grover |
1:4769360130ed | 141 | bool buffer_reached_its_capacity = outputBuffer_.reachedItsCapacity(); |
Rohit Grover |
1:4769360130ed | 142 | outputBuffer_.resetWriteLimit(); |
Rohit Grover |
1:4769360130ed | 143 | |
Rohit Grover |
1:4769360130ed | 144 | if (buffer_reached_its_capacity) |
Rohit Grover |
1:4769360130ed | 145 | addErrorMessageForTooMuchLeaks(); |
Rohit Grover |
1:4769360130ed | 146 | |
Rohit Grover |
1:4769360130ed | 147 | addMemoryLeakFooter(total_leaks_); |
Rohit Grover |
1:4769360130ed | 148 | |
Rohit Grover |
1:4769360130ed | 149 | if (giveWarningOnUsingMalloc_) |
Rohit Grover |
1:4769360130ed | 150 | addWarningForUsingMalloc(); |
Rohit Grover |
1:4769360130ed | 151 | |
Rohit Grover |
1:4769360130ed | 152 | } |
Rohit Grover |
1:4769360130ed | 153 | |
Rohit Grover |
1:4769360130ed | 154 | void MemoryLeakOutputStringBuffer::addMemoryLeakHeader() |
Rohit Grover |
1:4769360130ed | 155 | { |
Rohit Grover |
1:4769360130ed | 156 | outputBuffer_.add("Memory leak(s) found.\n"); |
Rohit Grover |
1:4769360130ed | 157 | } |
Rohit Grover |
1:4769360130ed | 158 | |
Rohit Grover |
1:4769360130ed | 159 | void MemoryLeakOutputStringBuffer::addErrorMessageForTooMuchLeaks() |
Rohit Grover |
1:4769360130ed | 160 | { |
Rohit Grover |
1:4769360130ed | 161 | outputBuffer_.add(MEM_LEAK_TOO_MUCH); |
Rohit Grover |
1:4769360130ed | 162 | } |
Rohit Grover |
1:4769360130ed | 163 | |
Rohit Grover |
1:4769360130ed | 164 | void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(int amountOfLeaks) |
Rohit Grover |
1:4769360130ed | 165 | { |
Rohit Grover |
1:4769360130ed | 166 | outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, amountOfLeaks); |
Rohit Grover |
1:4769360130ed | 167 | } |
Rohit Grover |
1:4769360130ed | 168 | |
Rohit Grover |
1:4769360130ed | 169 | void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc() |
Rohit Grover |
1:4769360130ed | 170 | { |
Rohit Grover |
1:4769360130ed | 171 | outputBuffer_.add(MEM_LEAK_ADDITION_MALLOC_WARNING); |
Rohit Grover |
1:4769360130ed | 172 | } |
Rohit Grover |
1:4769360130ed | 173 | |
Rohit Grover |
1:4769360130ed | 174 | void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) |
Rohit Grover |
1:4769360130ed | 175 | { |
Rohit Grover |
1:4769360130ed | 176 | reportFailure("Deallocating non-allocated memory\n", "<unknown>", 0, 0, NullUnknownAllocator::defaultAllocator(), freeFile, freeLine, freeAllocator, reporter); |
Rohit Grover |
1:4769360130ed | 177 | } |
Rohit Grover |
1:4769360130ed | 178 | |
Rohit Grover |
1:4769360130ed | 179 | void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) |
Rohit Grover |
1:4769360130ed | 180 | { |
Rohit Grover |
1:4769360130ed | 181 | reportFailure("Allocation/deallocation type mismatch\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter); |
Rohit Grover |
1:4769360130ed | 182 | } |
Rohit Grover |
1:4769360130ed | 183 | |
Rohit Grover |
1:4769360130ed | 184 | void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) |
Rohit Grover |
1:4769360130ed | 185 | { |
Rohit Grover |
1:4769360130ed | 186 | reportFailure("Memory corruption (written out of bounds?)\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter); |
Rohit Grover |
1:4769360130ed | 187 | } |
Rohit Grover |
1:4769360130ed | 188 | |
Rohit Grover |
1:4769360130ed | 189 | void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, int freeLine, |
Rohit Grover |
1:4769360130ed | 190 | TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) |
Rohit Grover |
1:4769360130ed | 191 | { |
Rohit Grover |
1:4769360130ed | 192 | outputBuffer_.add("%s", message); |
Rohit Grover |
1:4769360130ed | 193 | addAllocationLocation(allocFile, allocLine, allocSize, allocAllocator); |
Rohit Grover |
1:4769360130ed | 194 | addDeallocationLocation(freeFile, freeLine, freeAllocator); |
Rohit Grover |
1:4769360130ed | 195 | reporter->fail(toString()); |
Rohit Grover |
1:4769360130ed | 196 | } |
Rohit Grover |
1:4769360130ed | 197 | |
Rohit Grover |
1:4769360130ed | 198 | |
Rohit Grover |
1:4769360130ed | 199 | char* MemoryLeakOutputStringBuffer::toString() |
Rohit Grover |
1:4769360130ed | 200 | { |
Rohit Grover |
1:4769360130ed | 201 | return outputBuffer_.toString(); |
Rohit Grover |
1:4769360130ed | 202 | } |
Rohit Grover |
1:4769360130ed | 203 | |
Rohit Grover |
1:4769360130ed | 204 | void MemoryLeakOutputStringBuffer::clear() |
Rohit Grover |
1:4769360130ed | 205 | { |
Rohit Grover |
1:4769360130ed | 206 | outputBuffer_.clear(); |
Rohit Grover |
1:4769360130ed | 207 | } |
Rohit Grover |
1:4769360130ed | 208 | |
Rohit Grover |
1:4769360130ed | 209 | //////////////////////// |
Rohit Grover |
1:4769360130ed | 210 | |
Rohit Grover |
1:4769360130ed | 211 | void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line) |
Rohit Grover |
1:4769360130ed | 212 | { |
Rohit Grover |
1:4769360130ed | 213 | number_ = number; |
Rohit Grover |
1:4769360130ed | 214 | memory_ = memory; |
Rohit Grover |
1:4769360130ed | 215 | size_ = size; |
Rohit Grover |
1:4769360130ed | 216 | allocator_ = allocator; |
Rohit Grover |
1:4769360130ed | 217 | period_ = period; |
Rohit Grover |
1:4769360130ed | 218 | file_ = file; |
Rohit Grover |
1:4769360130ed | 219 | line_ = line; |
Rohit Grover |
1:4769360130ed | 220 | } |
Rohit Grover |
1:4769360130ed | 221 | |
Rohit Grover |
1:4769360130ed | 222 | /////////////////////// |
Rohit Grover |
1:4769360130ed | 223 | |
Rohit Grover |
1:4769360130ed | 224 | bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 225 | { |
Rohit Grover |
1:4769360130ed | 226 | return period == mem_leak_period_all || node->period_ == period || (node->period_ != mem_leak_period_disabled && period == mem_leak_period_enabled); |
Rohit Grover |
1:4769360130ed | 227 | } |
Rohit Grover |
1:4769360130ed | 228 | |
Rohit Grover |
1:4769360130ed | 229 | void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 230 | { |
Rohit Grover |
1:4769360130ed | 231 | MemoryLeakDetectorNode* cur = head_; |
Rohit Grover |
1:4769360130ed | 232 | MemoryLeakDetectorNode* prev = 0; |
Rohit Grover |
1:4769360130ed | 233 | |
Rohit Grover |
1:4769360130ed | 234 | while (cur) { |
Rohit Grover |
1:4769360130ed | 235 | if (isInPeriod(cur, period)) { |
Rohit Grover |
1:4769360130ed | 236 | if (prev) { |
Rohit Grover |
1:4769360130ed | 237 | prev->next_ = cur->next_; |
Rohit Grover |
1:4769360130ed | 238 | cur = prev; |
Rohit Grover |
1:4769360130ed | 239 | } |
Rohit Grover |
1:4769360130ed | 240 | else { |
Rohit Grover |
1:4769360130ed | 241 | head_ = cur->next_; |
Rohit Grover |
1:4769360130ed | 242 | cur = head_; |
Rohit Grover |
1:4769360130ed | 243 | continue; |
Rohit Grover |
1:4769360130ed | 244 | } |
Rohit Grover |
1:4769360130ed | 245 | } |
Rohit Grover |
1:4769360130ed | 246 | prev = cur; |
Rohit Grover |
1:4769360130ed | 247 | cur = cur->next_; |
Rohit Grover |
1:4769360130ed | 248 | } |
Rohit Grover |
1:4769360130ed | 249 | } |
Rohit Grover |
1:4769360130ed | 250 | |
Rohit Grover |
1:4769360130ed | 251 | void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node) |
Rohit Grover |
1:4769360130ed | 252 | { |
Rohit Grover |
1:4769360130ed | 253 | node->next_ = head_; |
Rohit Grover |
1:4769360130ed | 254 | head_ = node; |
Rohit Grover |
1:4769360130ed | 255 | } |
Rohit Grover |
1:4769360130ed | 256 | |
Rohit Grover |
1:4769360130ed | 257 | MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory) |
Rohit Grover |
1:4769360130ed | 258 | { |
Rohit Grover |
1:4769360130ed | 259 | MemoryLeakDetectorNode* cur = head_; |
Rohit Grover |
1:4769360130ed | 260 | MemoryLeakDetectorNode* prev = 0; |
Rohit Grover |
1:4769360130ed | 261 | while (cur) { |
Rohit Grover |
1:4769360130ed | 262 | if (cur->memory_ == memory) { |
Rohit Grover |
1:4769360130ed | 263 | if (prev) { |
Rohit Grover |
1:4769360130ed | 264 | prev->next_ = cur->next_; |
Rohit Grover |
1:4769360130ed | 265 | return cur; |
Rohit Grover |
1:4769360130ed | 266 | } |
Rohit Grover |
1:4769360130ed | 267 | else { |
Rohit Grover |
1:4769360130ed | 268 | head_ = cur->next_; |
Rohit Grover |
1:4769360130ed | 269 | return cur; |
Rohit Grover |
1:4769360130ed | 270 | } |
Rohit Grover |
1:4769360130ed | 271 | } |
Rohit Grover |
1:4769360130ed | 272 | prev = cur; |
Rohit Grover |
1:4769360130ed | 273 | cur = cur->next_; |
Rohit Grover |
1:4769360130ed | 274 | } |
Rohit Grover |
1:4769360130ed | 275 | return 0; |
Rohit Grover |
1:4769360130ed | 276 | } |
Rohit Grover |
1:4769360130ed | 277 | |
Rohit Grover |
1:4769360130ed | 278 | MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory) |
Rohit Grover |
1:4769360130ed | 279 | { |
Rohit Grover |
1:4769360130ed | 280 | MemoryLeakDetectorNode* cur = head_; |
Rohit Grover |
1:4769360130ed | 281 | while (cur) { |
Rohit Grover |
1:4769360130ed | 282 | if (cur->memory_ == memory) |
Rohit Grover |
1:4769360130ed | 283 | return cur; |
Rohit Grover |
1:4769360130ed | 284 | cur = cur->next_; |
Rohit Grover |
1:4769360130ed | 285 | } |
Rohit Grover |
1:4769360130ed | 286 | return NULL; |
Rohit Grover |
1:4769360130ed | 287 | } |
Rohit Grover |
1:4769360130ed | 288 | |
Rohit Grover |
1:4769360130ed | 289 | MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 290 | { |
Rohit Grover |
1:4769360130ed | 291 | for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_) |
Rohit Grover |
1:4769360130ed | 292 | if (isInPeriod(cur, period)) return cur; |
Rohit Grover |
1:4769360130ed | 293 | return 0; |
Rohit Grover |
1:4769360130ed | 294 | } |
Rohit Grover |
1:4769360130ed | 295 | |
Rohit Grover |
1:4769360130ed | 296 | MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 297 | { |
Rohit Grover |
1:4769360130ed | 298 | return getLeakFrom(head_, period); |
Rohit Grover |
1:4769360130ed | 299 | } |
Rohit Grover |
1:4769360130ed | 300 | |
Rohit Grover |
1:4769360130ed | 301 | MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 302 | { |
Rohit Grover |
1:4769360130ed | 303 | return getLeakFrom(node->next_, period); |
Rohit Grover |
1:4769360130ed | 304 | } |
Rohit Grover |
1:4769360130ed | 305 | |
Rohit Grover |
1:4769360130ed | 306 | int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 307 | { |
Rohit Grover |
1:4769360130ed | 308 | int total_leaks = 0; |
Rohit Grover |
1:4769360130ed | 309 | for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) { |
Rohit Grover |
1:4769360130ed | 310 | if (isInPeriod(node, period)) total_leaks++; |
Rohit Grover |
1:4769360130ed | 311 | } |
Rohit Grover |
1:4769360130ed | 312 | return total_leaks; |
Rohit Grover |
1:4769360130ed | 313 | } |
Rohit Grover |
1:4769360130ed | 314 | |
Rohit Grover |
1:4769360130ed | 315 | bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 316 | { |
Rohit Grover |
1:4769360130ed | 317 | for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) |
Rohit Grover |
1:4769360130ed | 318 | if (isInPeriod(node, period)) return true; |
Rohit Grover |
1:4769360130ed | 319 | return false; |
Rohit Grover |
1:4769360130ed | 320 | } |
Rohit Grover |
1:4769360130ed | 321 | |
Rohit Grover |
1:4769360130ed | 322 | ///////////////////////////////////////////////////////////// |
Rohit Grover |
1:4769360130ed | 323 | |
Rohit Grover |
1:4769360130ed | 324 | unsigned long MemoryLeakDetectorTable::hash(char* memory) |
Rohit Grover |
1:4769360130ed | 325 | { |
Rohit Grover |
1:4769360130ed | 326 | return (unsigned long)((size_t)memory % hash_prime); |
Rohit Grover |
1:4769360130ed | 327 | } |
Rohit Grover |
1:4769360130ed | 328 | |
Rohit Grover |
1:4769360130ed | 329 | void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 330 | { |
Rohit Grover |
1:4769360130ed | 331 | for (int i = 0; i < hash_prime; i++) |
Rohit Grover |
1:4769360130ed | 332 | table_[i].clearAllAccounting(period); |
Rohit Grover |
1:4769360130ed | 333 | } |
Rohit Grover |
1:4769360130ed | 334 | |
Rohit Grover |
1:4769360130ed | 335 | void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node) |
Rohit Grover |
1:4769360130ed | 336 | { |
Rohit Grover |
1:4769360130ed | 337 | table_[hash(node->memory_)].addNewNode(node); |
Rohit Grover |
1:4769360130ed | 338 | } |
Rohit Grover |
1:4769360130ed | 339 | |
Rohit Grover |
1:4769360130ed | 340 | MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory) |
Rohit Grover |
1:4769360130ed | 341 | { |
Rohit Grover |
1:4769360130ed | 342 | return table_[hash(memory)].removeNode(memory); |
Rohit Grover |
1:4769360130ed | 343 | } |
Rohit Grover |
1:4769360130ed | 344 | |
Rohit Grover |
1:4769360130ed | 345 | MemoryLeakDetectorNode* MemoryLeakDetectorTable::retrieveNode(char* memory) |
Rohit Grover |
1:4769360130ed | 346 | { |
Rohit Grover |
1:4769360130ed | 347 | return table_[hash(memory)].retrieveNode(memory); |
Rohit Grover |
1:4769360130ed | 348 | } |
Rohit Grover |
1:4769360130ed | 349 | |
Rohit Grover |
1:4769360130ed | 350 | bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 351 | { |
Rohit Grover |
1:4769360130ed | 352 | for (int i = 0; i < hash_prime; i++) |
Rohit Grover |
1:4769360130ed | 353 | if (table_[i].hasLeaks(period)) return true; |
Rohit Grover |
1:4769360130ed | 354 | return false; |
Rohit Grover |
1:4769360130ed | 355 | } |
Rohit Grover |
1:4769360130ed | 356 | |
Rohit Grover |
1:4769360130ed | 357 | int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 358 | { |
Rohit Grover |
1:4769360130ed | 359 | int total_leaks = 0; |
Rohit Grover |
1:4769360130ed | 360 | for (int i = 0; i < hash_prime; i++) |
Rohit Grover |
1:4769360130ed | 361 | total_leaks += table_[i].getTotalLeaks(period); |
Rohit Grover |
1:4769360130ed | 362 | return total_leaks; |
Rohit Grover |
1:4769360130ed | 363 | } |
Rohit Grover |
1:4769360130ed | 364 | |
Rohit Grover |
1:4769360130ed | 365 | MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 366 | { |
Rohit Grover |
1:4769360130ed | 367 | for (int i = 0; i < hash_prime; i++) { |
Rohit Grover |
1:4769360130ed | 368 | MemoryLeakDetectorNode* node = table_[i].getFirstLeak(period); |
Rohit Grover |
1:4769360130ed | 369 | if (node) return node; |
Rohit Grover |
1:4769360130ed | 370 | } |
Rohit Grover |
1:4769360130ed | 371 | return 0; |
Rohit Grover |
1:4769360130ed | 372 | } |
Rohit Grover |
1:4769360130ed | 373 | |
Rohit Grover |
1:4769360130ed | 374 | MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 375 | { |
Rohit Grover |
1:4769360130ed | 376 | unsigned long i = hash(leak->memory_); |
Rohit Grover |
1:4769360130ed | 377 | MemoryLeakDetectorNode* node = table_[i].getNextLeak(leak, period); |
Rohit Grover |
1:4769360130ed | 378 | if (node) return node; |
Rohit Grover |
1:4769360130ed | 379 | |
Rohit Grover |
1:4769360130ed | 380 | for (++i; i < hash_prime; i++) { |
Rohit Grover |
1:4769360130ed | 381 | node = table_[i].getFirstLeak(period); |
Rohit Grover |
1:4769360130ed | 382 | if (node) return node; |
Rohit Grover |
1:4769360130ed | 383 | } |
Rohit Grover |
1:4769360130ed | 384 | return 0; |
Rohit Grover |
1:4769360130ed | 385 | } |
Rohit Grover |
1:4769360130ed | 386 | |
Rohit Grover |
1:4769360130ed | 387 | ///////////////////////////////////////////////////////////// |
Rohit Grover |
1:4769360130ed | 388 | |
Rohit Grover |
1:4769360130ed | 389 | MemoryLeakDetector::MemoryLeakDetector(MemoryLeakFailure* reporter) |
Rohit Grover |
1:4769360130ed | 390 | { |
Rohit Grover |
1:4769360130ed | 391 | doAllocationTypeChecking_ = true; |
Rohit Grover |
1:4769360130ed | 392 | allocationSequenceNumber_ = 1; |
Rohit Grover |
1:4769360130ed | 393 | current_period_ = mem_leak_period_disabled; |
Rohit Grover |
1:4769360130ed | 394 | reporter_ = reporter; |
Rohit Grover |
1:4769360130ed | 395 | outputBuffer_ = MemoryLeakOutputStringBuffer(); |
Rohit Grover |
1:4769360130ed | 396 | memoryTable_ = MemoryLeakDetectorTable(); |
Rohit Grover |
1:4769360130ed | 397 | } |
Rohit Grover |
1:4769360130ed | 398 | |
Rohit Grover |
1:4769360130ed | 399 | void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 400 | { |
Rohit Grover |
1:4769360130ed | 401 | memoryTable_.clearAllAccounting(period); |
Rohit Grover |
1:4769360130ed | 402 | } |
Rohit Grover |
1:4769360130ed | 403 | |
Rohit Grover |
1:4769360130ed | 404 | void MemoryLeakDetector::startChecking() |
Rohit Grover |
1:4769360130ed | 405 | { |
Rohit Grover |
1:4769360130ed | 406 | outputBuffer_.clear(); |
Rohit Grover |
1:4769360130ed | 407 | current_period_ = mem_leak_period_checking; |
Rohit Grover |
1:4769360130ed | 408 | } |
Rohit Grover |
1:4769360130ed | 409 | |
Rohit Grover |
1:4769360130ed | 410 | void MemoryLeakDetector::stopChecking() |
Rohit Grover |
1:4769360130ed | 411 | { |
Rohit Grover |
1:4769360130ed | 412 | current_period_ = mem_leak_period_enabled; |
Rohit Grover |
1:4769360130ed | 413 | } |
Rohit Grover |
1:4769360130ed | 414 | |
Rohit Grover |
1:4769360130ed | 415 | void MemoryLeakDetector::enable() |
Rohit Grover |
1:4769360130ed | 416 | { |
Rohit Grover |
1:4769360130ed | 417 | current_period_ = mem_leak_period_enabled; |
Rohit Grover |
1:4769360130ed | 418 | } |
Rohit Grover |
1:4769360130ed | 419 | |
Rohit Grover |
1:4769360130ed | 420 | void MemoryLeakDetector::disable() |
Rohit Grover |
1:4769360130ed | 421 | { |
Rohit Grover |
1:4769360130ed | 422 | current_period_ = mem_leak_period_disabled; |
Rohit Grover |
1:4769360130ed | 423 | } |
Rohit Grover |
1:4769360130ed | 424 | |
Rohit Grover |
1:4769360130ed | 425 | void MemoryLeakDetector::disableAllocationTypeChecking() |
Rohit Grover |
1:4769360130ed | 426 | { |
Rohit Grover |
1:4769360130ed | 427 | doAllocationTypeChecking_ = false; |
Rohit Grover |
1:4769360130ed | 428 | } |
Rohit Grover |
1:4769360130ed | 429 | |
Rohit Grover |
1:4769360130ed | 430 | void MemoryLeakDetector::enableAllocationTypeChecking() |
Rohit Grover |
1:4769360130ed | 431 | { |
Rohit Grover |
1:4769360130ed | 432 | doAllocationTypeChecking_ = true; |
Rohit Grover |
1:4769360130ed | 433 | } |
Rohit Grover |
1:4769360130ed | 434 | |
Rohit Grover |
1:4769360130ed | 435 | unsigned MemoryLeakDetector::getCurrentAllocationNumber() |
Rohit Grover |
1:4769360130ed | 436 | { |
Rohit Grover |
1:4769360130ed | 437 | return allocationSequenceNumber_; |
Rohit Grover |
1:4769360130ed | 438 | } |
Rohit Grover |
1:4769360130ed | 439 | |
Rohit Grover |
1:4769360130ed | 440 | static size_t calculateVoidPointerAlignedSize(size_t size) |
Rohit Grover |
1:4769360130ed | 441 | { |
Rohit Grover |
1:4769360130ed | 442 | return (sizeof(void*) - (size % sizeof(void*))) + size; |
Rohit Grover |
1:4769360130ed | 443 | } |
Rohit Grover |
1:4769360130ed | 444 | |
Rohit Grover |
1:4769360130ed | 445 | size_t MemoryLeakDetector::sizeOfMemoryWithCorruptionInfo(size_t size) |
Rohit Grover |
1:4769360130ed | 446 | { |
Rohit Grover |
1:4769360130ed | 447 | return calculateVoidPointerAlignedSize(size + memory_corruption_buffer_size); |
Rohit Grover |
1:4769360130ed | 448 | } |
Rohit Grover |
1:4769360130ed | 449 | |
Rohit Grover |
1:4769360130ed | 450 | MemoryLeakDetectorNode* MemoryLeakDetector::getNodeFromMemoryPointer(char* memory, size_t memory_size) |
Rohit Grover |
1:4769360130ed | 451 | { |
Rohit Grover |
1:4769360130ed | 452 | return (MemoryLeakDetectorNode*) (void*) (memory + sizeOfMemoryWithCorruptionInfo(memory_size)); |
Rohit Grover |
1:4769360130ed | 453 | } |
Rohit Grover |
1:4769360130ed | 454 | |
Rohit Grover |
1:4769360130ed | 455 | void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line) |
Rohit Grover |
1:4769360130ed | 456 | { |
Rohit Grover |
1:4769360130ed | 457 | node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, file, line); |
Rohit Grover |
1:4769360130ed | 458 | addMemoryCorruptionInformation(node->memory_ + node->size_); |
Rohit Grover |
1:4769360130ed | 459 | memoryTable_.addNewNode(node); |
Rohit Grover |
1:4769360130ed | 460 | } |
Rohit Grover |
1:4769360130ed | 461 | |
Rohit Grover |
1:4769360130ed | 462 | char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 463 | { |
Rohit Grover |
1:4769360130ed | 464 | char* new_memory = reallocateMemoryWithAccountingInformation(allocator, memory, size, file, line, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 465 | if (new_memory == NULL) return NULL; |
Rohit Grover |
1:4769360130ed | 466 | |
Rohit Grover |
1:4769360130ed | 467 | MemoryLeakDetectorNode *node = createMemoryLeakAccountingInformation(allocator, size, new_memory, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 468 | storeLeakInformation(node, new_memory, size, allocator, file, line); |
Rohit Grover |
1:4769360130ed | 469 | return node->memory_; |
Rohit Grover |
1:4769360130ed | 470 | } |
Rohit Grover |
1:4769360130ed | 471 | |
Rohit Grover |
1:4769360130ed | 472 | void MemoryLeakDetector::invalidateMemory(char* memory) |
Rohit Grover |
1:4769360130ed | 473 | { |
Rohit Grover |
1:4769360130ed | 474 | MemoryLeakDetectorNode* node = memoryTable_.retrieveNode(memory); |
Rohit Grover |
1:4769360130ed | 475 | if (node) |
Rohit Grover |
1:4769360130ed | 476 | PlatformSpecificMemset(memory, 0xCD, node->size_); |
Rohit Grover |
1:4769360130ed | 477 | } |
Rohit Grover |
1:4769360130ed | 478 | |
Rohit Grover |
1:4769360130ed | 479 | void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory) |
Rohit Grover |
1:4769360130ed | 480 | { |
Rohit Grover |
1:4769360130ed | 481 | memory[0] = 'B'; |
Rohit Grover |
1:4769360130ed | 482 | memory[1] = 'A'; |
Rohit Grover |
1:4769360130ed | 483 | memory[2] = 'S'; |
Rohit Grover |
1:4769360130ed | 484 | } |
Rohit Grover |
1:4769360130ed | 485 | |
Rohit Grover |
1:4769360130ed | 486 | bool MemoryLeakDetector::validMemoryCorruptionInformation(char* memory) |
Rohit Grover |
1:4769360130ed | 487 | { |
Rohit Grover |
1:4769360130ed | 488 | return memory[0] == 'B' && memory[1] == 'A' && memory[2] == 'S'; |
Rohit Grover |
1:4769360130ed | 489 | } |
Rohit Grover |
1:4769360130ed | 490 | |
Rohit Grover |
1:4769360130ed | 491 | bool MemoryLeakDetector::matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator) |
Rohit Grover |
1:4769360130ed | 492 | { |
Rohit Grover |
1:4769360130ed | 493 | if (alloc_allocator == free_allocator) return true; |
Rohit Grover |
1:4769360130ed | 494 | if (!doAllocationTypeChecking_) return true; |
Rohit Grover |
1:4769360130ed | 495 | return free_allocator->isOfEqualType(alloc_allocator); |
Rohit Grover |
1:4769360130ed | 496 | } |
Rohit Grover |
1:4769360130ed | 497 | |
Rohit Grover |
1:4769360130ed | 498 | void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately) |
Rohit Grover |
1:4769360130ed | 499 | { |
Rohit Grover |
1:4769360130ed | 500 | if (!matchingAllocation(node->allocator_, allocator)) |
Rohit Grover |
1:4769360130ed | 501 | outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator, reporter_); |
Rohit Grover |
1:4769360130ed | 502 | else if (!validMemoryCorruptionInformation(node->memory_ + node->size_)) |
Rohit Grover |
1:4769360130ed | 503 | outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator, reporter_); |
Rohit Grover |
1:4769360130ed | 504 | else if (allocateNodesSeperately) |
Rohit Grover |
1:4769360130ed | 505 | allocator->freeMemoryLeakNode((char*) node); |
Rohit Grover |
1:4769360130ed | 506 | } |
Rohit Grover |
1:4769360130ed | 507 | |
Rohit Grover |
1:4769360130ed | 508 | char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 509 | { |
Rohit Grover |
1:4769360130ed | 510 | return allocMemory(allocator, size, UNKNOWN, 0, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 511 | } |
Rohit Grover |
1:4769360130ed | 512 | |
Rohit Grover |
1:4769360130ed | 513 | char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 514 | { |
Rohit Grover |
1:4769360130ed | 515 | if (allocatNodesSeperately) return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size), file, line); |
Rohit Grover |
1:4769360130ed | 516 | else return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode), file, line); |
Rohit Grover |
1:4769360130ed | 517 | } |
Rohit Grover |
1:4769360130ed | 518 | |
Rohit Grover |
1:4769360130ed | 519 | char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, int /*line*/, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 520 | { |
Rohit Grover |
1:4769360130ed | 521 | if (allocatNodesSeperately) return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size)); |
Rohit Grover |
1:4769360130ed | 522 | else return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode)); |
Rohit Grover |
1:4769360130ed | 523 | } |
Rohit Grover |
1:4769360130ed | 524 | |
Rohit Grover |
1:4769360130ed | 525 | MemoryLeakDetectorNode* MemoryLeakDetector::createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 526 | { |
Rohit Grover |
1:4769360130ed | 527 | if (allocatNodesSeperately) return (MemoryLeakDetectorNode*) (void*) allocator->allocMemoryLeakNode(sizeof(MemoryLeakDetectorNode)); |
Rohit Grover |
1:4769360130ed | 528 | else return getNodeFromMemoryPointer(memory, size); |
Rohit Grover |
1:4769360130ed | 529 | } |
Rohit Grover |
1:4769360130ed | 530 | |
Rohit Grover |
1:4769360130ed | 531 | char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 532 | { |
Rohit Grover |
1:4769360130ed | 533 | /* With malloc, it is harder to guarantee that the allocator free is called. |
Rohit Grover |
1:4769360130ed | 534 | * This is because operator new is overloaded via linker symbols, but malloc just via #defines. |
Rohit Grover |
1:4769360130ed | 535 | * If the same allocation is used and the wrong free is called, it will deallocate the memory leak information |
Rohit Grover |
1:4769360130ed | 536 | * without the memory leak detector ever noticing it! |
Rohit Grover |
1:4769360130ed | 537 | * So, for malloc, we'll allocate the memory separately so we can detect this and give a proper error. |
Rohit Grover |
1:4769360130ed | 538 | */ |
Rohit Grover |
1:4769360130ed | 539 | |
Rohit Grover |
1:4769360130ed | 540 | char* memory = allocateMemoryWithAccountingInformation(allocator, size, file, line, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 541 | if (memory == NULL) return NULL; |
Rohit Grover |
1:4769360130ed | 542 | MemoryLeakDetectorNode* node = createMemoryLeakAccountingInformation(allocator, size, memory, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 543 | |
Rohit Grover |
1:4769360130ed | 544 | storeLeakInformation(node, memory, size, allocator, file, line); |
Rohit Grover |
1:4769360130ed | 545 | return node->memory_; |
Rohit Grover |
1:4769360130ed | 546 | } |
Rohit Grover |
1:4769360130ed | 547 | |
Rohit Grover |
1:4769360130ed | 548 | void MemoryLeakDetector::removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 549 | { |
Rohit Grover |
1:4769360130ed | 550 | MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory); |
Rohit Grover |
1:4769360130ed | 551 | if (allocatNodesSeperately) allocator->freeMemoryLeakNode( (char*) node); |
Rohit Grover |
1:4769360130ed | 552 | } |
Rohit Grover |
1:4769360130ed | 553 | |
Rohit Grover |
1:4769360130ed | 554 | void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 555 | { |
Rohit Grover |
1:4769360130ed | 556 | if (memory == 0) return; |
Rohit Grover |
1:4769360130ed | 557 | |
Rohit Grover |
1:4769360130ed | 558 | MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory); |
Rohit Grover |
1:4769360130ed | 559 | if (node == NULL) { |
Rohit Grover |
1:4769360130ed | 560 | outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_); |
Rohit Grover |
1:4769360130ed | 561 | return; |
Rohit Grover |
1:4769360130ed | 562 | } |
Rohit Grover |
1:4769360130ed | 563 | if (!allocator->hasBeenDestroyed()) { |
Rohit Grover |
1:4769360130ed | 564 | checkForCorruption(node, file, line, allocator, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 565 | allocator->free_memory((char*) memory, file, line); |
Rohit Grover |
1:4769360130ed | 566 | } |
Rohit Grover |
1:4769360130ed | 567 | } |
Rohit Grover |
1:4769360130ed | 568 | |
Rohit Grover |
1:4769360130ed | 569 | void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 570 | { |
Rohit Grover |
1:4769360130ed | 571 | deallocMemory(allocator, (char*) memory, UNKNOWN, 0, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 572 | } |
Rohit Grover |
1:4769360130ed | 573 | |
Rohit Grover |
1:4769360130ed | 574 | char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately) |
Rohit Grover |
1:4769360130ed | 575 | { |
Rohit Grover |
1:4769360130ed | 576 | if (memory) { |
Rohit Grover |
1:4769360130ed | 577 | MemoryLeakDetectorNode* node = memoryTable_.removeNode(memory); |
Rohit Grover |
1:4769360130ed | 578 | if (node == NULL) { |
Rohit Grover |
1:4769360130ed | 579 | outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_); |
Rohit Grover |
1:4769360130ed | 580 | return NULL; |
Rohit Grover |
1:4769360130ed | 581 | } |
Rohit Grover |
1:4769360130ed | 582 | checkForCorruption(node, file, line, allocator, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 583 | } |
Rohit Grover |
1:4769360130ed | 584 | return reallocateMemoryAndLeakInformation(allocator, memory, size, file, line, allocatNodesSeperately); |
Rohit Grover |
1:4769360130ed | 585 | } |
Rohit Grover |
1:4769360130ed | 586 | |
Rohit Grover |
1:4769360130ed | 587 | void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 588 | { |
Rohit Grover |
1:4769360130ed | 589 | MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(period); |
Rohit Grover |
1:4769360130ed | 590 | |
Rohit Grover |
1:4769360130ed | 591 | outputBuffer_.startMemoryLeakReporting(); |
Rohit Grover |
1:4769360130ed | 592 | |
Rohit Grover |
1:4769360130ed | 593 | while (leak) { |
Rohit Grover |
1:4769360130ed | 594 | outputBuffer_.reportMemoryLeak(leak); |
Rohit Grover |
1:4769360130ed | 595 | leak = memoryTable_.getNextLeak(leak, period); |
Rohit Grover |
1:4769360130ed | 596 | } |
Rohit Grover |
1:4769360130ed | 597 | |
Rohit Grover |
1:4769360130ed | 598 | outputBuffer_.stopMemoryLeakReporting(); |
Rohit Grover |
1:4769360130ed | 599 | } |
Rohit Grover |
1:4769360130ed | 600 | |
Rohit Grover |
1:4769360130ed | 601 | const char* MemoryLeakDetector::report(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 602 | { |
Rohit Grover |
1:4769360130ed | 603 | outputBuffer_.clear(); |
Rohit Grover |
1:4769360130ed | 604 | ConstructMemoryLeakReport(period); |
Rohit Grover |
1:4769360130ed | 605 | |
Rohit Grover |
1:4769360130ed | 606 | return outputBuffer_.toString(); |
Rohit Grover |
1:4769360130ed | 607 | } |
Rohit Grover |
1:4769360130ed | 608 | |
Rohit Grover |
1:4769360130ed | 609 | void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod() |
Rohit Grover |
1:4769360130ed | 610 | { |
Rohit Grover |
1:4769360130ed | 611 | MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(mem_leak_period_checking); |
Rohit Grover |
1:4769360130ed | 612 | while (leak) { |
Rohit Grover |
1:4769360130ed | 613 | if (leak->period_ == mem_leak_period_checking) leak->period_ = mem_leak_period_enabled; |
Rohit Grover |
1:4769360130ed | 614 | leak = memoryTable_.getNextLeak(leak, mem_leak_period_checking); |
Rohit Grover |
1:4769360130ed | 615 | } |
Rohit Grover |
1:4769360130ed | 616 | } |
Rohit Grover |
1:4769360130ed | 617 | |
Rohit Grover |
1:4769360130ed | 618 | int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period) |
Rohit Grover |
1:4769360130ed | 619 | { |
Rohit Grover |
1:4769360130ed | 620 | return memoryTable_.getTotalLeaks(period); |
Rohit Grover |
1:4769360130ed | 621 | } |