fork

Fork of cpputest by Rohit Grover

Committer:
rgrover1
Date:
Tue Jan 28 09:27:41 2014 +0000
Revision:
0:0b799af9d58e
Child:
1:4769360130ed
CppUTest unit test framework.

Who changed what in which revision?

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