Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
MemoryLeakDetector.cpp
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 #include "CppUTest/TestHarness.h" 00028 #include "CppUTest/MemoryLeakDetector.h" 00029 #include "CppUTest/TestMemoryAllocator.h" 00030 #include "CppUTest/PlatformSpecificFunctions.h" 00031 00032 #define UNKNOWN ((char*)("<unknown>")) 00033 00034 SimpleStringBuffer::SimpleStringBuffer() : 00035 positions_filled_(0), write_limit_(SIMPLE_STRING_BUFFER_LEN-1) 00036 { 00037 } 00038 00039 void SimpleStringBuffer::clear() 00040 { 00041 positions_filled_ = 0; 00042 buffer_[0] = '\0'; 00043 } 00044 00045 void SimpleStringBuffer::add(const char* format, ...) 00046 { 00047 int count = 0; 00048 size_t positions_left = write_limit_ - positions_filled_; 00049 if (positions_left <= 0) return; 00050 00051 va_list arguments; 00052 va_start(arguments, format); 00053 count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments); 00054 if (count > 0) positions_filled_ += (size_t) count; 00055 if (positions_filled_ > write_limit_) positions_filled_ = write_limit_; 00056 va_end(arguments); 00057 } 00058 00059 char* SimpleStringBuffer::toString() 00060 { 00061 return buffer_; 00062 } 00063 00064 void SimpleStringBuffer::setWriteLimit(size_t write_limit) 00065 { 00066 write_limit_ = write_limit; 00067 if (write_limit_ > SIMPLE_STRING_BUFFER_LEN-1) 00068 write_limit_ = SIMPLE_STRING_BUFFER_LEN-1; 00069 } 00070 void SimpleStringBuffer::resetWriteLimit() 00071 { 00072 write_limit_ = SIMPLE_STRING_BUFFER_LEN-1; 00073 } 00074 00075 bool SimpleStringBuffer::reachedItsCapacity() 00076 { 00077 return positions_filled_ >= write_limit_; 00078 } 00079 00080 //////////////////////// 00081 00082 #define MEM_LEAK_TOO_MUCH "\netc etc etc etc. !!!! Too much memory leaks to report. Bailing out\n" 00083 #define MEM_LEAK_FOOTER "Total number of leaks: " 00084 #define MEM_LEAK_ADDITION_MALLOC_WARNING "NOTE:\n" \ 00085 "\tMemory leak reports about malloc and free can be caused by allocating using the cpputest version of malloc,\n" \ 00086 "\tbut deallocate using the standard free.\n" \ 00087 "\tIf this is the case, check whether your malloc/free replacements are working (#define malloc cpputest_malloc etc).\n" 00088 00089 MemoryLeakOutputStringBuffer::MemoryLeakOutputStringBuffer() 00090 : total_leaks_(0), giveWarningOnUsingMalloc_(false) 00091 { 00092 } 00093 00094 void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator) 00095 { 00096 outputBuffer_.add(" allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name()); 00097 } 00098 00099 void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator) 00100 { 00101 outputBuffer_.add(" deallocated at file: %s line: %d type: %s\n", freeFile, freeLineNumber, allocator->free_name()); 00102 } 00103 00104 void MemoryLeakOutputStringBuffer::addNoMemoryLeaksMessage() 00105 { 00106 outputBuffer_.add("No memory leaks were detected."); 00107 } 00108 00109 void MemoryLeakOutputStringBuffer::startMemoryLeakReporting() 00110 { 00111 giveWarningOnUsingMalloc_ = false; 00112 total_leaks_ = 0; 00113 00114 size_t memory_leak_normal_footer_size = sizeof(MEM_LEAK_FOOTER) + 10 + sizeof(MEM_LEAK_TOO_MUCH); /* the number of leaks */ 00115 size_t memory_leak_foot_size_with_malloc_warning = memory_leak_normal_footer_size + sizeof(MEM_LEAK_ADDITION_MALLOC_WARNING); 00116 00117 outputBuffer_.setWriteLimit(SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN - memory_leak_foot_size_with_malloc_warning); 00118 } 00119 00120 void MemoryLeakOutputStringBuffer::reportMemoryLeak(MemoryLeakDetectorNode* leak) 00121 { 00122 if (total_leaks_ == 0) { 00123 addMemoryLeakHeader(); 00124 } 00125 00126 total_leaks_++; 00127 outputBuffer_.add("Alloc num (%u) Leak size: %lu Allocated at: %s and line: %d. Type: \"%s\"\n\t Memory: <%p> Content: \"%.15s\"\n", 00128 leak->number_, (unsigned long) leak->size_, leak->file_, leak->line_, leak->allocator_->alloc_name(), leak->memory_, leak->memory_); 00129 00130 if (PlatformSpecificStrCmp(leak->allocator_->alloc_name(), "malloc") == 0) 00131 giveWarningOnUsingMalloc_ = true; 00132 } 00133 00134 void MemoryLeakOutputStringBuffer::stopMemoryLeakReporting() 00135 { 00136 if (total_leaks_ == 0) { 00137 addNoMemoryLeaksMessage(); 00138 return; 00139 } 00140 00141 bool buffer_reached_its_capacity = outputBuffer_.reachedItsCapacity(); 00142 outputBuffer_.resetWriteLimit(); 00143 00144 if (buffer_reached_its_capacity) 00145 addErrorMessageForTooMuchLeaks(); 00146 00147 addMemoryLeakFooter(total_leaks_); 00148 00149 if (giveWarningOnUsingMalloc_) 00150 addWarningForUsingMalloc(); 00151 00152 } 00153 00154 void MemoryLeakOutputStringBuffer::addMemoryLeakHeader() 00155 { 00156 outputBuffer_.add("Memory leak(s) found.\n"); 00157 } 00158 00159 void MemoryLeakOutputStringBuffer::addErrorMessageForTooMuchLeaks() 00160 { 00161 outputBuffer_.add(MEM_LEAK_TOO_MUCH); 00162 } 00163 00164 void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(int amountOfLeaks) 00165 { 00166 outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, amountOfLeaks); 00167 } 00168 00169 void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc() 00170 { 00171 outputBuffer_.add(MEM_LEAK_ADDITION_MALLOC_WARNING); 00172 } 00173 00174 void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) 00175 { 00176 reportFailure("Deallocating non-allocated memory\n", "<unknown>", 0, 0, NullUnknownAllocator::defaultAllocator(), freeFile, freeLine, freeAllocator, reporter); 00177 } 00178 00179 void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) 00180 { 00181 reportFailure("Allocation/deallocation type mismatch\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter); 00182 } 00183 00184 void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) 00185 { 00186 reportFailure("Memory corruption (written out of bounds?)\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter); 00187 } 00188 00189 void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, int freeLine, 00190 TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter) 00191 { 00192 outputBuffer_.add("%s", message); 00193 addAllocationLocation(allocFile, allocLine, allocSize, allocAllocator); 00194 addDeallocationLocation(freeFile, freeLine, freeAllocator); 00195 reporter->fail(toString()); 00196 } 00197 00198 00199 char* MemoryLeakOutputStringBuffer::toString() 00200 { 00201 return outputBuffer_.toString(); 00202 } 00203 00204 void MemoryLeakOutputStringBuffer::clear() 00205 { 00206 outputBuffer_.clear(); 00207 } 00208 00209 //////////////////////// 00210 00211 void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line) 00212 { 00213 number_ = number; 00214 memory_ = memory; 00215 size_ = size; 00216 allocator_ = allocator; 00217 period_ = period; 00218 file_ = file; 00219 line_ = line; 00220 } 00221 00222 /////////////////////// 00223 00224 bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period) 00225 { 00226 return period == mem_leak_period_all || node->period_ == period || (node->period_ != mem_leak_period_disabled && period == mem_leak_period_enabled); 00227 } 00228 00229 void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period) 00230 { 00231 MemoryLeakDetectorNode* cur = head_; 00232 MemoryLeakDetectorNode* prev = 0; 00233 00234 while (cur) { 00235 if (isInPeriod(cur, period)) { 00236 if (prev) { 00237 prev->next_ = cur->next_; 00238 cur = prev; 00239 } 00240 else { 00241 head_ = cur->next_; 00242 cur = head_; 00243 continue; 00244 } 00245 } 00246 prev = cur; 00247 cur = cur->next_; 00248 } 00249 } 00250 00251 void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node) 00252 { 00253 node->next_ = head_; 00254 head_ = node; 00255 } 00256 00257 MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory) 00258 { 00259 MemoryLeakDetectorNode* cur = head_; 00260 MemoryLeakDetectorNode* prev = 0; 00261 while (cur) { 00262 if (cur->memory_ == memory) { 00263 if (prev) { 00264 prev->next_ = cur->next_; 00265 return cur; 00266 } 00267 else { 00268 head_ = cur->next_; 00269 return cur; 00270 } 00271 } 00272 prev = cur; 00273 cur = cur->next_; 00274 } 00275 return 0; 00276 } 00277 00278 MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory) 00279 { 00280 MemoryLeakDetectorNode* cur = head_; 00281 while (cur) { 00282 if (cur->memory_ == memory) 00283 return cur; 00284 cur = cur->next_; 00285 } 00286 return NULL; 00287 } 00288 00289 MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period) 00290 { 00291 for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_) 00292 if (isInPeriod(cur, period)) return cur; 00293 return 0; 00294 } 00295 00296 MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period) 00297 { 00298 return getLeakFrom(head_, period); 00299 } 00300 00301 MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period) 00302 { 00303 return getLeakFrom(node->next_, period); 00304 } 00305 00306 int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period) 00307 { 00308 int total_leaks = 0; 00309 for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) { 00310 if (isInPeriod(node, period)) total_leaks++; 00311 } 00312 return total_leaks; 00313 } 00314 00315 bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period) 00316 { 00317 for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) 00318 if (isInPeriod(node, period)) return true; 00319 return false; 00320 } 00321 00322 ///////////////////////////////////////////////////////////// 00323 00324 unsigned long MemoryLeakDetectorTable::hash(char* memory) 00325 { 00326 return (unsigned long)((size_t)memory % hash_prime); 00327 } 00328 00329 void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period) 00330 { 00331 for (int i = 0; i < hash_prime; i++) 00332 table_[i].clearAllAccounting(period); 00333 } 00334 00335 void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node) 00336 { 00337 table_[hash(node->memory_)].addNewNode(node); 00338 } 00339 00340 MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory) 00341 { 00342 return table_[hash(memory)].removeNode(memory); 00343 } 00344 00345 MemoryLeakDetectorNode* MemoryLeakDetectorTable::retrieveNode(char* memory) 00346 { 00347 return table_[hash(memory)].retrieveNode(memory); 00348 } 00349 00350 bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period) 00351 { 00352 for (int i = 0; i < hash_prime; i++) 00353 if (table_[i].hasLeaks(period)) return true; 00354 return false; 00355 } 00356 00357 int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period) 00358 { 00359 int total_leaks = 0; 00360 for (int i = 0; i < hash_prime; i++) 00361 total_leaks += table_[i].getTotalLeaks(period); 00362 return total_leaks; 00363 } 00364 00365 MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period) 00366 { 00367 for (int i = 0; i < hash_prime; i++) { 00368 MemoryLeakDetectorNode* node = table_[i].getFirstLeak(period); 00369 if (node) return node; 00370 } 00371 return 0; 00372 } 00373 00374 MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period) 00375 { 00376 unsigned long i = hash(leak->memory_); 00377 MemoryLeakDetectorNode* node = table_[i].getNextLeak(leak, period); 00378 if (node) return node; 00379 00380 for (++i; i < hash_prime; i++) { 00381 node = table_[i].getFirstLeak(period); 00382 if (node) return node; 00383 } 00384 return 0; 00385 } 00386 00387 ///////////////////////////////////////////////////////////// 00388 00389 MemoryLeakDetector::MemoryLeakDetector(MemoryLeakFailure* reporter) 00390 { 00391 doAllocationTypeChecking_ = true; 00392 allocationSequenceNumber_ = 1; 00393 current_period_ = mem_leak_period_disabled; 00394 reporter_ = reporter; 00395 outputBuffer_ = MemoryLeakOutputStringBuffer(); 00396 memoryTable_ = MemoryLeakDetectorTable(); 00397 } 00398 00399 void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period) 00400 { 00401 memoryTable_.clearAllAccounting(period); 00402 } 00403 00404 void MemoryLeakDetector::startChecking() 00405 { 00406 outputBuffer_.clear(); 00407 current_period_ = mem_leak_period_checking; 00408 } 00409 00410 void MemoryLeakDetector::stopChecking() 00411 { 00412 current_period_ = mem_leak_period_enabled; 00413 } 00414 00415 void MemoryLeakDetector::enable() 00416 { 00417 current_period_ = mem_leak_period_enabled; 00418 } 00419 00420 void MemoryLeakDetector::disable() 00421 { 00422 current_period_ = mem_leak_period_disabled; 00423 } 00424 00425 void MemoryLeakDetector::disableAllocationTypeChecking() 00426 { 00427 doAllocationTypeChecking_ = false; 00428 } 00429 00430 void MemoryLeakDetector::enableAllocationTypeChecking() 00431 { 00432 doAllocationTypeChecking_ = true; 00433 } 00434 00435 unsigned MemoryLeakDetector::getCurrentAllocationNumber() 00436 { 00437 return allocationSequenceNumber_; 00438 } 00439 00440 static size_t calculateVoidPointerAlignedSize(size_t size) 00441 { 00442 return (sizeof(void*) - (size % sizeof(void*))) + size; 00443 } 00444 00445 size_t MemoryLeakDetector::sizeOfMemoryWithCorruptionInfo(size_t size) 00446 { 00447 return calculateVoidPointerAlignedSize(size + memory_corruption_buffer_size); 00448 } 00449 00450 MemoryLeakDetectorNode* MemoryLeakDetector::getNodeFromMemoryPointer(char* memory, size_t memory_size) 00451 { 00452 return (MemoryLeakDetectorNode*) (void*) (memory + sizeOfMemoryWithCorruptionInfo(memory_size)); 00453 } 00454 00455 void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line) 00456 { 00457 node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, file, line); 00458 addMemoryCorruptionInformation(node->memory_ + node->size_); 00459 memoryTable_.addNewNode(node); 00460 } 00461 00462 char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately) 00463 { 00464 char* new_memory = reallocateMemoryWithAccountingInformation(allocator, memory, size, file, line, allocatNodesSeperately); 00465 if (new_memory == NULL) return NULL; 00466 00467 MemoryLeakDetectorNode *node = createMemoryLeakAccountingInformation(allocator, size, new_memory, allocatNodesSeperately); 00468 storeLeakInformation(node, new_memory, size, allocator, file, line); 00469 return node->memory_; 00470 } 00471 00472 void MemoryLeakDetector::invalidateMemory(char* memory) 00473 { 00474 MemoryLeakDetectorNode* node = memoryTable_.retrieveNode(memory); 00475 if (node) 00476 PlatformSpecificMemset(memory, 0xCD, node->size_); 00477 } 00478 00479 void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory) 00480 { 00481 memory[0] = 'B'; 00482 memory[1] = 'A'; 00483 memory[2] = 'S'; 00484 } 00485 00486 bool MemoryLeakDetector::validMemoryCorruptionInformation(char* memory) 00487 { 00488 return memory[0] == 'B' && memory[1] == 'A' && memory[2] == 'S'; 00489 } 00490 00491 bool MemoryLeakDetector::matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator) 00492 { 00493 if (alloc_allocator == free_allocator) return true; 00494 if (!doAllocationTypeChecking_) return true; 00495 return free_allocator->isOfEqualType(alloc_allocator); 00496 } 00497 00498 void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately) 00499 { 00500 if (!matchingAllocation(node->allocator_, allocator)) 00501 outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator, reporter_); 00502 else if (!validMemoryCorruptionInformation(node->memory_ + node->size_)) 00503 outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator, reporter_); 00504 else if (allocateNodesSeperately) 00505 allocator->freeMemoryLeakNode((char*) node); 00506 } 00507 00508 char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately) 00509 { 00510 return allocMemory(allocator, size, UNKNOWN, 0, allocatNodesSeperately); 00511 } 00512 00513 char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately) 00514 { 00515 if (allocatNodesSeperately) return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size), file, line); 00516 else return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode), file, line); 00517 } 00518 00519 char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, int /*line*/, bool allocatNodesSeperately) 00520 { 00521 if (allocatNodesSeperately) return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size)); 00522 else return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode)); 00523 } 00524 00525 MemoryLeakDetectorNode* MemoryLeakDetector::createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately) 00526 { 00527 if (allocatNodesSeperately) return (MemoryLeakDetectorNode*) (void*) allocator->allocMemoryLeakNode(sizeof(MemoryLeakDetectorNode)); 00528 else return getNodeFromMemoryPointer(memory, size); 00529 } 00530 00531 char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately) 00532 { 00533 /* With malloc, it is harder to guarantee that the allocator free is called. 00534 * This is because operator new is overloaded via linker symbols, but malloc just via #defines. 00535 * If the same allocation is used and the wrong free is called, it will deallocate the memory leak information 00536 * without the memory leak detector ever noticing it! 00537 * So, for malloc, we'll allocate the memory separately so we can detect this and give a proper error. 00538 */ 00539 00540 char* memory = allocateMemoryWithAccountingInformation(allocator, size, file, line, allocatNodesSeperately); 00541 if (memory == NULL) return NULL; 00542 MemoryLeakDetectorNode* node = createMemoryLeakAccountingInformation(allocator, size, memory, allocatNodesSeperately); 00543 00544 storeLeakInformation(node, memory, size, allocator, file, line); 00545 return node->memory_; 00546 } 00547 00548 void MemoryLeakDetector::removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately) 00549 { 00550 MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory); 00551 if (allocatNodesSeperately) allocator->freeMemoryLeakNode( (char*) node); 00552 } 00553 00554 void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately) 00555 { 00556 if (memory == 0) return; 00557 00558 MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory); 00559 if (node == NULL) { 00560 outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_); 00561 return; 00562 } 00563 if (!allocator->hasBeenDestroyed()) { 00564 checkForCorruption(node, file, line, allocator, allocatNodesSeperately); 00565 allocator->free_memory((char*) memory, file, line); 00566 } 00567 } 00568 00569 void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately) 00570 { 00571 deallocMemory(allocator, (char*) memory, UNKNOWN, 0, allocatNodesSeperately); 00572 } 00573 00574 char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately) 00575 { 00576 if (memory) { 00577 MemoryLeakDetectorNode* node = memoryTable_.removeNode(memory); 00578 if (node == NULL) { 00579 outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_); 00580 return NULL; 00581 } 00582 checkForCorruption(node, file, line, allocator, allocatNodesSeperately); 00583 } 00584 return reallocateMemoryAndLeakInformation(allocator, memory, size, file, line, allocatNodesSeperately); 00585 } 00586 00587 void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period) 00588 { 00589 MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(period); 00590 00591 outputBuffer_.startMemoryLeakReporting(); 00592 00593 while (leak) { 00594 outputBuffer_.reportMemoryLeak(leak); 00595 leak = memoryTable_.getNextLeak(leak, period); 00596 } 00597 00598 outputBuffer_.stopMemoryLeakReporting(); 00599 } 00600 00601 const char* MemoryLeakDetector::report(MemLeakPeriod period) 00602 { 00603 outputBuffer_.clear(); 00604 ConstructMemoryLeakReport(period); 00605 00606 return outputBuffer_.toString(); 00607 } 00608 00609 void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod() 00610 { 00611 MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(mem_leak_period_checking); 00612 while (leak) { 00613 if (leak->period_ == mem_leak_period_checking) leak->period_ = mem_leak_period_enabled; 00614 leak = memoryTable_.getNextLeak(leak, mem_leak_period_checking); 00615 } 00616 } 00617 00618 int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period) 00619 { 00620 return memoryTable_.getTotalLeaks(period); 00621 }
Generated on Fri Jul 15 2022 01:46:32 by
1.7.2