fork

Fork of cpputest by Rohit Grover

Revision:
1:4769360130ed
Parent:
0:0b799af9d58e
--- a/src/CppUTest/MemoryLeakDetector.cpp	Tue Jan 28 09:27:41 2014 +0000
+++ b/src/CppUTest/MemoryLeakDetector.cpp	Tue Jun 17 15:52:54 2014 +0100
@@ -1,621 +1,621 @@
-/*
- * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the <organization> nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "CppUTest/TestHarness.h"
-#include "CppUTest/MemoryLeakDetector.h"
-#include "CppUTest/TestMemoryAllocator.h"
-#include "CppUTest/PlatformSpecificFunctions.h"
-
-#define UNKNOWN ((char*)("<unknown>"))
-
-SimpleStringBuffer::SimpleStringBuffer() :
-	positions_filled_(0), write_limit_(SIMPLE_STRING_BUFFER_LEN-1)
-{
-}
-
-void SimpleStringBuffer::clear()
-{
-	positions_filled_ = 0;
-	buffer_[0] = '\0';
-}
-
-void SimpleStringBuffer::add(const char* format, ...)
-{
-	int count = 0;
-	size_t positions_left = write_limit_ - positions_filled_;
-	if (positions_left <= 0) return;
-
-	va_list arguments;
-	va_start(arguments, format);
-	count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments);
-    if (count > 0) positions_filled_ += (size_t) count;
-	if (positions_filled_ > write_limit_) positions_filled_ = write_limit_;
-	va_end(arguments);
-}
-
-char* SimpleStringBuffer::toString()
-{
-	return buffer_;
-}
-
-void SimpleStringBuffer::setWriteLimit(size_t write_limit)
-{
-	write_limit_ = write_limit;
-	if (write_limit_ > SIMPLE_STRING_BUFFER_LEN-1)
-		write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
-}
-void SimpleStringBuffer::resetWriteLimit()
-{
-	write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
-}
-
-bool SimpleStringBuffer::reachedItsCapacity()
-{
-	return positions_filled_ >= write_limit_;
-}
-
-////////////////////////
-
-#define MEM_LEAK_TOO_MUCH "\netc etc etc etc. !!!! Too much memory leaks to report. Bailing out\n"
-#define MEM_LEAK_FOOTER "Total number of leaks: "
-#define MEM_LEAK_ADDITION_MALLOC_WARNING "NOTE:\n" \
-										 "\tMemory leak reports about malloc and free can be caused by allocating using the cpputest version of malloc,\n" \
-										 "\tbut deallocate using the standard free.\n" \
-										 "\tIf this is the case, check whether your malloc/free replacements are working (#define malloc cpputest_malloc etc).\n"
-
-MemoryLeakOutputStringBuffer::MemoryLeakOutputStringBuffer()
-	: total_leaks_(0), giveWarningOnUsingMalloc_(false)
-{
-}
-
-void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator)
-{
-	outputBuffer_.add("   allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name());
-}
-
-void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator)
-{
-	outputBuffer_.add("   deallocated at file: %s line: %d type: %s\n", freeFile, freeLineNumber, allocator->free_name());
-}
-
-void MemoryLeakOutputStringBuffer::addNoMemoryLeaksMessage()
-{
-	outputBuffer_.add("No memory leaks were detected.");
-}
-
-void MemoryLeakOutputStringBuffer::startMemoryLeakReporting()
-{
-	giveWarningOnUsingMalloc_ = false;
-	total_leaks_ = 0;
-
-	size_t memory_leak_normal_footer_size = sizeof(MEM_LEAK_FOOTER) + 10 + sizeof(MEM_LEAK_TOO_MUCH); /* the number of leaks */
-	size_t memory_leak_foot_size_with_malloc_warning = memory_leak_normal_footer_size + sizeof(MEM_LEAK_ADDITION_MALLOC_WARNING);
-
-	outputBuffer_.setWriteLimit(SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN - memory_leak_foot_size_with_malloc_warning);
-}
-
-void MemoryLeakOutputStringBuffer::reportMemoryLeak(MemoryLeakDetectorNode* leak)
-{
-	if (total_leaks_ == 0) {
-		addMemoryLeakHeader();
-	}
-
-	total_leaks_++;
-	outputBuffer_.add("Alloc num (%u) Leak size: %lu Allocated at: %s and line: %d. Type: \"%s\"\n\t Memory: <%p> Content: \"%.15s\"\n",
-			leak->number_, (unsigned long) leak->size_, leak->file_, leak->line_, leak->allocator_->alloc_name(), leak->memory_, leak->memory_);
-
-	if (PlatformSpecificStrCmp(leak->allocator_->alloc_name(), "malloc") == 0)
-		giveWarningOnUsingMalloc_ = true;
-}
-
-void MemoryLeakOutputStringBuffer::stopMemoryLeakReporting()
-{
-	if (total_leaks_ == 0) {
-		addNoMemoryLeaksMessage();
-		return;
-	}
-
-	bool buffer_reached_its_capacity = outputBuffer_.reachedItsCapacity();
-	outputBuffer_.resetWriteLimit();
-
-	if (buffer_reached_its_capacity)
-		addErrorMessageForTooMuchLeaks();
-
-	addMemoryLeakFooter(total_leaks_);
-
-	if (giveWarningOnUsingMalloc_)
-		addWarningForUsingMalloc();
-
-}
-
-void MemoryLeakOutputStringBuffer::addMemoryLeakHeader()
-{
-	outputBuffer_.add("Memory leak(s) found.\n");
-}
-
-void MemoryLeakOutputStringBuffer::addErrorMessageForTooMuchLeaks()
-{
-	outputBuffer_.add(MEM_LEAK_TOO_MUCH);
-}
-
-void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(int amountOfLeaks)
-{
-	outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, amountOfLeaks);
-}
-
-void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc()
-{
-	outputBuffer_.add(MEM_LEAK_ADDITION_MALLOC_WARNING);
-}
-
-void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
-	reportFailure("Deallocating non-allocated memory\n", "<unknown>", 0, 0, NullUnknownAllocator::defaultAllocator(), freeFile, freeLine, freeAllocator, reporter);
-}
-
-void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
-	reportFailure("Allocation/deallocation type mismatch\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
-}
-
-void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
-		reportFailure("Memory corruption (written out of bounds?)\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
-}
-
-void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, int freeLine,
-		TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
-{
-	outputBuffer_.add("%s", message);
-	addAllocationLocation(allocFile, allocLine, allocSize, allocAllocator);
-	addDeallocationLocation(freeFile, freeLine, freeAllocator);
-	reporter->fail(toString());
-}
-
-
-char* MemoryLeakOutputStringBuffer::toString()
-{
-	return outputBuffer_.toString();
-}
-
-void MemoryLeakOutputStringBuffer::clear()
-{
-	outputBuffer_.clear();
-}
-
-////////////////////////
-
-void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line)
-{
-	number_ = number;
-	memory_ = memory;
-	size_ = size;
-	allocator_ = allocator;
-	period_ = period;
-	file_ = file;
-	line_ = line;
-}
-
-///////////////////////
-
-bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period)
-{
-	return period == mem_leak_period_all || node->period_ == period || (node->period_ != mem_leak_period_disabled && period == mem_leak_period_enabled);
-}
-
-void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period)
-{
-	MemoryLeakDetectorNode* cur = head_;
-	MemoryLeakDetectorNode* prev = 0;
-
-	while (cur) {
-		if (isInPeriod(cur, period)) {
-			if (prev) {
-				prev->next_ = cur->next_;
-				cur = prev;
-			}
-			else {
-				head_ = cur->next_;
-				cur = head_;
-				continue;
-			}
-		}
-		prev = cur;
-		cur = cur->next_;
-	}
-}
-
-void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node)
-{
-	node->next_ = head_;
-	head_ = node;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
-{
-	MemoryLeakDetectorNode* cur = head_;
-	MemoryLeakDetectorNode* prev = 0;
-	while (cur) {
-		if (cur->memory_ == memory) {
-			if (prev) {
-				prev->next_ = cur->next_;
-				return cur;
-			}
-			else {
-				head_ = cur->next_;
-				return cur;
-			}
-		}
-		prev = cur;
-		cur = cur->next_;
-	}
-	return 0;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory)
-{
-  MemoryLeakDetectorNode* cur = head_;
-  while (cur) {
-    if (cur->memory_ == memory)
-      return cur;
-    cur = cur->next_;
-  }
-  return NULL;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period)
-{
-	for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_)
-		if (isInPeriod(cur, period)) return cur;
-	return 0;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period)
-{
-	return getLeakFrom(head_, period);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period)
-{
-	return getLeakFrom(node->next_, period);
-}
-
-int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
-{
-	int total_leaks = 0;
-	for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) {
-		if (isInPeriod(node, period)) total_leaks++;
-	}
-	return total_leaks;
-}
-
-bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period)
-{
-	for (MemoryLeakDetectorNode* node = head_; node; node = node->next_)
-		if (isInPeriod(node, period)) return true;
-	return false;
-}
-
-/////////////////////////////////////////////////////////////
-
-unsigned long MemoryLeakDetectorTable::hash(char* memory)
-{
-	return (unsigned long)((size_t)memory % hash_prime);
-}
-
-void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period)
-{
-	for (int i = 0; i < hash_prime; i++)
-		table_[i].clearAllAccounting(period);
-}
-
-void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node)
-{
-	table_[hash(node->memory_)].addNewNode(node);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory)
-{
-	return table_[hash(memory)].removeNode(memory);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::retrieveNode(char* memory)
-{
-  return table_[hash(memory)].retrieveNode(memory);
-}
-
-bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period)
-{
-	for (int i = 0; i < hash_prime; i++)
-		if (table_[i].hasLeaks(period)) return true;
-	return false;
-}
-
-int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
-{
-	int total_leaks = 0;
-	for (int i = 0; i < hash_prime; i++)
-		total_leaks += table_[i].getTotalLeaks(period);
-	return total_leaks;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period)
-{
-	for (int i = 0; i < hash_prime; i++) {
-		MemoryLeakDetectorNode* node = table_[i].getFirstLeak(period);
-		if (node) return node;
-	}
-	return 0;
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period)
-{
-	unsigned long i = hash(leak->memory_);
-	MemoryLeakDetectorNode* node = table_[i].getNextLeak(leak, period);
-	if (node) return node;
-
-	for (++i; i < hash_prime; i++) {
-		node = table_[i].getFirstLeak(period);
-		if (node) return node;
-	}
-	return 0;
-}
-
-/////////////////////////////////////////////////////////////
-
-MemoryLeakDetector::MemoryLeakDetector(MemoryLeakFailure* reporter)
-{
-	doAllocationTypeChecking_ = true;
-	allocationSequenceNumber_ = 1;
-	current_period_ = mem_leak_period_disabled;
-	reporter_ = reporter;
-	outputBuffer_ = MemoryLeakOutputStringBuffer();
-	memoryTable_ = MemoryLeakDetectorTable();
-}
-
-void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period)
-{
-	memoryTable_.clearAllAccounting(period);
-}
-
-void MemoryLeakDetector::startChecking()
-{
-	outputBuffer_.clear();
-	current_period_ = mem_leak_period_checking;
-}
-
-void MemoryLeakDetector::stopChecking()
-{
-	current_period_ = mem_leak_period_enabled;
-}
-
-void MemoryLeakDetector::enable()
-{
-	current_period_ = mem_leak_period_enabled;
-}
-
-void MemoryLeakDetector::disable()
-{
-	current_period_ = mem_leak_period_disabled;
-}
-
-void MemoryLeakDetector::disableAllocationTypeChecking()
-{
-	doAllocationTypeChecking_ = false;
-}
-
-void MemoryLeakDetector::enableAllocationTypeChecking()
-{
-	doAllocationTypeChecking_ = true;
-}
-
-unsigned MemoryLeakDetector::getCurrentAllocationNumber()
-{
-	return allocationSequenceNumber_;
-}
-
-static size_t calculateVoidPointerAlignedSize(size_t size)
-{
-	return (sizeof(void*) - (size % sizeof(void*))) + size;
-}
-
-size_t MemoryLeakDetector::sizeOfMemoryWithCorruptionInfo(size_t size)
-{
-	return calculateVoidPointerAlignedSize(size + memory_corruption_buffer_size);
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetector::getNodeFromMemoryPointer(char* memory, size_t memory_size)
-{
-	return (MemoryLeakDetectorNode*) (void*) (memory + sizeOfMemoryWithCorruptionInfo(memory_size));
-}
-
-void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line)
-{
-	node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, file, line);
-	addMemoryCorruptionInformation(node->memory_ + node->size_);
-	memoryTable_.addNewNode(node);
-}
-
-char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
-	char* new_memory = reallocateMemoryWithAccountingInformation(allocator, memory, size, file, line, allocatNodesSeperately);
-	if (new_memory == NULL) return NULL;
-
-	MemoryLeakDetectorNode *node = createMemoryLeakAccountingInformation(allocator, size, new_memory, allocatNodesSeperately);
-	storeLeakInformation(node, new_memory, size, allocator, file, line);
-	return node->memory_;
-}
-
-void MemoryLeakDetector::invalidateMemory(char* memory)
-{
-  MemoryLeakDetectorNode* node = memoryTable_.retrieveNode(memory);
-  if (node)
-    PlatformSpecificMemset(memory, 0xCD, node->size_);
-}
-
-void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory)
-{
-	memory[0] = 'B';
-	memory[1] = 'A';
-	memory[2] = 'S';
-}
-
-bool MemoryLeakDetector::validMemoryCorruptionInformation(char* memory)
-{
-	return memory[0] == 'B' && memory[1] == 'A' && memory[2] == 'S';
-}
-
-bool MemoryLeakDetector::matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator)
-{
-	if (alloc_allocator == free_allocator) return true;
-	if (!doAllocationTypeChecking_) return true;
-	return free_allocator->isOfEqualType(alloc_allocator);
-}
-
-void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately)
-{
-	if (!matchingAllocation(node->allocator_, allocator))
-		outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator, reporter_);
-	else if (!validMemoryCorruptionInformation(node->memory_ + node->size_))
-		outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator, reporter_);
-	else if (allocateNodesSeperately)
-		allocator->freeMemoryLeakNode((char*) node);
-}
-
-char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately)
-{
-	return allocMemory(allocator, size, UNKNOWN, 0, allocatNodesSeperately);
-}
-
-char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
-	if (allocatNodesSeperately) return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size), file, line);
-	else return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode), file, line);
-}
-
-char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, int /*line*/, bool allocatNodesSeperately)
-{
-	if (allocatNodesSeperately) return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size));
-	else return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode));
-}
-
-MemoryLeakDetectorNode* MemoryLeakDetector::createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately)
-{
-	if (allocatNodesSeperately) return (MemoryLeakDetectorNode*) (void*) allocator->allocMemoryLeakNode(sizeof(MemoryLeakDetectorNode));
-	else return getNodeFromMemoryPointer(memory, size);
-}
-
-char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
-	/* With malloc, it is harder to guarantee that the allocator free is called.
-	 * This is because operator new is overloaded via linker symbols, but malloc just via #defines.
-	 * If the same allocation is used and the wrong free is called, it will deallocate the memory leak information
-	 * without the memory leak detector ever noticing it!
-	 * So, for malloc, we'll allocate the memory separately so we can detect this and give a proper error.
-	 */
-
-	char* memory = allocateMemoryWithAccountingInformation(allocator, size, file, line, allocatNodesSeperately);
-	if (memory == NULL) return NULL;
-	MemoryLeakDetectorNode* node = createMemoryLeakAccountingInformation(allocator, size, memory, allocatNodesSeperately);
-
-	storeLeakInformation(node, memory, size, allocator, file, line);
-	return node->memory_;
-}
-
-void MemoryLeakDetector::removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
-{
-	MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
-	if (allocatNodesSeperately) allocator->freeMemoryLeakNode( (char*) node);
-}
-
-void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately)
-{
-	if (memory == 0) return;
-
-	MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
-	if (node == NULL) {
-		outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
-		return;
-	}
-	if (!allocator->hasBeenDestroyed()) {
-		checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
-		allocator->free_memory((char*) memory, file, line);
-	}
-}
-
-void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
-{
-	deallocMemory(allocator, (char*) memory, UNKNOWN, 0, allocatNodesSeperately);
-}
-
-char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
-{
-	if (memory) {
-		MemoryLeakDetectorNode* node = memoryTable_.removeNode(memory);
-		if (node == NULL) {
-			outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
-			return NULL;
-		}
-		checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
-	}
-	return reallocateMemoryAndLeakInformation(allocator, memory, size, file, line, allocatNodesSeperately);
-}
-
-void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period)
-{
-	MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(period);
-
-	outputBuffer_.startMemoryLeakReporting();
-
-	while (leak) {
-		outputBuffer_.reportMemoryLeak(leak);
-		leak = memoryTable_.getNextLeak(leak, period);
-	}
-
-	outputBuffer_.stopMemoryLeakReporting();
-}
-
-const char* MemoryLeakDetector::report(MemLeakPeriod period)
-{
-	outputBuffer_.clear();
-	ConstructMemoryLeakReport(period);
-
-	return outputBuffer_.toString();
-}
-
-void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod()
-{
-	MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(mem_leak_period_checking);
-	while (leak) {
-		if (leak->period_ == mem_leak_period_checking) leak->period_ = mem_leak_period_enabled;
-		leak = memoryTable_.getNextLeak(leak, mem_leak_period_checking);
-	}
-}
-
-int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
-{
-	return memoryTable_.getTotalLeaks(period);
-}
+/*
+ * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the <organization> nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE EARLIER MENTIONED AUTHORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/MemoryLeakDetector.h"
+#include "CppUTest/TestMemoryAllocator.h"
+#include "CppUTest/PlatformSpecificFunctions.h"
+
+#define UNKNOWN ((char*)("<unknown>"))
+
+SimpleStringBuffer::SimpleStringBuffer() :
+	positions_filled_(0), write_limit_(SIMPLE_STRING_BUFFER_LEN-1)
+{
+}
+
+void SimpleStringBuffer::clear()
+{
+	positions_filled_ = 0;
+	buffer_[0] = '\0';
+}
+
+void SimpleStringBuffer::add(const char* format, ...)
+{
+	int count = 0;
+	size_t positions_left = write_limit_ - positions_filled_;
+	if (positions_left <= 0) return;
+
+	va_list arguments;
+	va_start(arguments, format);
+	count = PlatformSpecificVSNprintf(buffer_ + positions_filled_, positions_left+1, format, arguments);
+    if (count > 0) positions_filled_ += (size_t) count;
+	if (positions_filled_ > write_limit_) positions_filled_ = write_limit_;
+	va_end(arguments);
+}
+
+char* SimpleStringBuffer::toString()
+{
+	return buffer_;
+}
+
+void SimpleStringBuffer::setWriteLimit(size_t write_limit)
+{
+	write_limit_ = write_limit;
+	if (write_limit_ > SIMPLE_STRING_BUFFER_LEN-1)
+		write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
+}
+void SimpleStringBuffer::resetWriteLimit()
+{
+	write_limit_ = SIMPLE_STRING_BUFFER_LEN-1;
+}
+
+bool SimpleStringBuffer::reachedItsCapacity()
+{
+	return positions_filled_ >= write_limit_;
+}
+
+////////////////////////
+
+#define MEM_LEAK_TOO_MUCH "\netc etc etc etc. !!!! Too much memory leaks to report. Bailing out\n"
+#define MEM_LEAK_FOOTER "Total number of leaks: "
+#define MEM_LEAK_ADDITION_MALLOC_WARNING "NOTE:\n" \
+										 "\tMemory leak reports about malloc and free can be caused by allocating using the cpputest version of malloc,\n" \
+										 "\tbut deallocate using the standard free.\n" \
+										 "\tIf this is the case, check whether your malloc/free replacements are working (#define malloc cpputest_malloc etc).\n"
+
+MemoryLeakOutputStringBuffer::MemoryLeakOutputStringBuffer()
+	: total_leaks_(0), giveWarningOnUsingMalloc_(false)
+{
+}
+
+void MemoryLeakOutputStringBuffer::addAllocationLocation(const char* allocationFile, int allocationLineNumber, size_t allocationSize, TestMemoryAllocator* allocator)
+{
+	outputBuffer_.add("   allocated at file: %s line: %d size: %lu type: %s\n", allocationFile, allocationLineNumber, (unsigned long) allocationSize, allocator->alloc_name());
+}
+
+void MemoryLeakOutputStringBuffer::addDeallocationLocation(const char* freeFile, int freeLineNumber, TestMemoryAllocator* allocator)
+{
+	outputBuffer_.add("   deallocated at file: %s line: %d type: %s\n", freeFile, freeLineNumber, allocator->free_name());
+}
+
+void MemoryLeakOutputStringBuffer::addNoMemoryLeaksMessage()
+{
+	outputBuffer_.add("No memory leaks were detected.");
+}
+
+void MemoryLeakOutputStringBuffer::startMemoryLeakReporting()
+{
+	giveWarningOnUsingMalloc_ = false;
+	total_leaks_ = 0;
+
+	size_t memory_leak_normal_footer_size = sizeof(MEM_LEAK_FOOTER) + 10 + sizeof(MEM_LEAK_TOO_MUCH); /* the number of leaks */
+	size_t memory_leak_foot_size_with_malloc_warning = memory_leak_normal_footer_size + sizeof(MEM_LEAK_ADDITION_MALLOC_WARNING);
+
+	outputBuffer_.setWriteLimit(SimpleStringBuffer::SIMPLE_STRING_BUFFER_LEN - memory_leak_foot_size_with_malloc_warning);
+}
+
+void MemoryLeakOutputStringBuffer::reportMemoryLeak(MemoryLeakDetectorNode* leak)
+{
+	if (total_leaks_ == 0) {
+		addMemoryLeakHeader();
+	}
+
+	total_leaks_++;
+	outputBuffer_.add("Alloc num (%u) Leak size: %lu Allocated at: %s and line: %d. Type: \"%s\"\n\t Memory: <%p> Content: \"%.15s\"\n",
+			leak->number_, (unsigned long) leak->size_, leak->file_, leak->line_, leak->allocator_->alloc_name(), leak->memory_, leak->memory_);
+
+	if (PlatformSpecificStrCmp(leak->allocator_->alloc_name(), "malloc") == 0)
+		giveWarningOnUsingMalloc_ = true;
+}
+
+void MemoryLeakOutputStringBuffer::stopMemoryLeakReporting()
+{
+	if (total_leaks_ == 0) {
+		addNoMemoryLeaksMessage();
+		return;
+	}
+
+	bool buffer_reached_its_capacity = outputBuffer_.reachedItsCapacity();
+	outputBuffer_.resetWriteLimit();
+
+	if (buffer_reached_its_capacity)
+		addErrorMessageForTooMuchLeaks();
+
+	addMemoryLeakFooter(total_leaks_);
+
+	if (giveWarningOnUsingMalloc_)
+		addWarningForUsingMalloc();
+
+}
+
+void MemoryLeakOutputStringBuffer::addMemoryLeakHeader()
+{
+	outputBuffer_.add("Memory leak(s) found.\n");
+}
+
+void MemoryLeakOutputStringBuffer::addErrorMessageForTooMuchLeaks()
+{
+	outputBuffer_.add(MEM_LEAK_TOO_MUCH);
+}
+
+void MemoryLeakOutputStringBuffer::addMemoryLeakFooter(int amountOfLeaks)
+{
+	outputBuffer_.add("%s %d\n", MEM_LEAK_FOOTER, amountOfLeaks);
+}
+
+void MemoryLeakOutputStringBuffer::addWarningForUsingMalloc()
+{
+	outputBuffer_.add(MEM_LEAK_ADDITION_MALLOC_WARNING);
+}
+
+void MemoryLeakOutputStringBuffer::reportDeallocateNonAllocatedMemoryFailure(const char* freeFile, int freeLine, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+	reportFailure("Deallocating non-allocated memory\n", "<unknown>", 0, 0, NullUnknownAllocator::defaultAllocator(), freeFile, freeLine, freeAllocator, reporter);
+}
+
+void MemoryLeakOutputStringBuffer::reportAllocationDeallocationMismatchFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+	reportFailure("Allocation/deallocation type mismatch\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
+}
+
+void MemoryLeakOutputStringBuffer::reportMemoryCorruptionFailure(MemoryLeakDetectorNode* node, const char* freeFile, int freeLineNumber, TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+		reportFailure("Memory corruption (written out of bounds?)\n", node->file_, node->line_, node->size_, node->allocator_, freeFile, freeLineNumber, freeAllocator, reporter);
+}
+
+void MemoryLeakOutputStringBuffer::reportFailure(const char* message, const char* allocFile, int allocLine, size_t allocSize, TestMemoryAllocator* allocAllocator, const char* freeFile, int freeLine,
+		TestMemoryAllocator* freeAllocator, MemoryLeakFailure* reporter)
+{
+	outputBuffer_.add("%s", message);
+	addAllocationLocation(allocFile, allocLine, allocSize, allocAllocator);
+	addDeallocationLocation(freeFile, freeLine, freeAllocator);
+	reporter->fail(toString());
+}
+
+
+char* MemoryLeakOutputStringBuffer::toString()
+{
+	return outputBuffer_.toString();
+}
+
+void MemoryLeakOutputStringBuffer::clear()
+{
+	outputBuffer_.clear();
+}
+
+////////////////////////
+
+void MemoryLeakDetectorNode::init(char* memory, unsigned number, size_t size, TestMemoryAllocator* allocator, MemLeakPeriod period, const char* file, int line)
+{
+	number_ = number;
+	memory_ = memory;
+	size_ = size;
+	allocator_ = allocator;
+	period_ = period;
+	file_ = file;
+	line_ = line;
+}
+
+///////////////////////
+
+bool MemoryLeakDetectorList::isInPeriod(MemoryLeakDetectorNode* node, MemLeakPeriod period)
+{
+	return period == mem_leak_period_all || node->period_ == period || (node->period_ != mem_leak_period_disabled && period == mem_leak_period_enabled);
+}
+
+void MemoryLeakDetectorList::clearAllAccounting(MemLeakPeriod period)
+{
+	MemoryLeakDetectorNode* cur = head_;
+	MemoryLeakDetectorNode* prev = 0;
+
+	while (cur) {
+		if (isInPeriod(cur, period)) {
+			if (prev) {
+				prev->next_ = cur->next_;
+				cur = prev;
+			}
+			else {
+				head_ = cur->next_;
+				cur = head_;
+				continue;
+			}
+		}
+		prev = cur;
+		cur = cur->next_;
+	}
+}
+
+void MemoryLeakDetectorList::addNewNode(MemoryLeakDetectorNode* node)
+{
+	node->next_ = head_;
+	head_ = node;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::removeNode(char* memory)
+{
+	MemoryLeakDetectorNode* cur = head_;
+	MemoryLeakDetectorNode* prev = 0;
+	while (cur) {
+		if (cur->memory_ == memory) {
+			if (prev) {
+				prev->next_ = cur->next_;
+				return cur;
+			}
+			else {
+				head_ = cur->next_;
+				return cur;
+			}
+		}
+		prev = cur;
+		cur = cur->next_;
+	}
+	return 0;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::retrieveNode(char* memory)
+{
+  MemoryLeakDetectorNode* cur = head_;
+  while (cur) {
+    if (cur->memory_ == memory)
+      return cur;
+    cur = cur->next_;
+  }
+  return NULL;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getLeakFrom(MemoryLeakDetectorNode* node, MemLeakPeriod period)
+{
+	for (MemoryLeakDetectorNode* cur = node; cur; cur = cur->next_)
+		if (isInPeriod(cur, period)) return cur;
+	return 0;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getFirstLeak(MemLeakPeriod period)
+{
+	return getLeakFrom(head_, period);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorList::getNextLeak(MemoryLeakDetectorNode* node, MemLeakPeriod period)
+{
+	return getLeakFrom(node->next_, period);
+}
+
+int MemoryLeakDetectorList::getTotalLeaks(MemLeakPeriod period)
+{
+	int total_leaks = 0;
+	for (MemoryLeakDetectorNode* node = head_; node; node = node->next_) {
+		if (isInPeriod(node, period)) total_leaks++;
+	}
+	return total_leaks;
+}
+
+bool MemoryLeakDetectorList::hasLeaks(MemLeakPeriod period)
+{
+	for (MemoryLeakDetectorNode* node = head_; node; node = node->next_)
+		if (isInPeriod(node, period)) return true;
+	return false;
+}
+
+/////////////////////////////////////////////////////////////
+
+unsigned long MemoryLeakDetectorTable::hash(char* memory)
+{
+	return (unsigned long)((size_t)memory % hash_prime);
+}
+
+void MemoryLeakDetectorTable::clearAllAccounting(MemLeakPeriod period)
+{
+	for (int i = 0; i < hash_prime; i++)
+		table_[i].clearAllAccounting(period);
+}
+
+void MemoryLeakDetectorTable::addNewNode(MemoryLeakDetectorNode* node)
+{
+	table_[hash(node->memory_)].addNewNode(node);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::removeNode(char* memory)
+{
+	return table_[hash(memory)].removeNode(memory);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::retrieveNode(char* memory)
+{
+  return table_[hash(memory)].retrieveNode(memory);
+}
+
+bool MemoryLeakDetectorTable::hasLeaks(MemLeakPeriod period)
+{
+	for (int i = 0; i < hash_prime; i++)
+		if (table_[i].hasLeaks(period)) return true;
+	return false;
+}
+
+int MemoryLeakDetectorTable::getTotalLeaks(MemLeakPeriod period)
+{
+	int total_leaks = 0;
+	for (int i = 0; i < hash_prime; i++)
+		total_leaks += table_[i].getTotalLeaks(period);
+	return total_leaks;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::getFirstLeak(MemLeakPeriod period)
+{
+	for (int i = 0; i < hash_prime; i++) {
+		MemoryLeakDetectorNode* node = table_[i].getFirstLeak(period);
+		if (node) return node;
+	}
+	return 0;
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetectorTable::getNextLeak(MemoryLeakDetectorNode* leak, MemLeakPeriod period)
+{
+	unsigned long i = hash(leak->memory_);
+	MemoryLeakDetectorNode* node = table_[i].getNextLeak(leak, period);
+	if (node) return node;
+
+	for (++i; i < hash_prime; i++) {
+		node = table_[i].getFirstLeak(period);
+		if (node) return node;
+	}
+	return 0;
+}
+
+/////////////////////////////////////////////////////////////
+
+MemoryLeakDetector::MemoryLeakDetector(MemoryLeakFailure* reporter)
+{
+	doAllocationTypeChecking_ = true;
+	allocationSequenceNumber_ = 1;
+	current_period_ = mem_leak_period_disabled;
+	reporter_ = reporter;
+	outputBuffer_ = MemoryLeakOutputStringBuffer();
+	memoryTable_ = MemoryLeakDetectorTable();
+}
+
+void MemoryLeakDetector::clearAllAccounting(MemLeakPeriod period)
+{
+	memoryTable_.clearAllAccounting(period);
+}
+
+void MemoryLeakDetector::startChecking()
+{
+	outputBuffer_.clear();
+	current_period_ = mem_leak_period_checking;
+}
+
+void MemoryLeakDetector::stopChecking()
+{
+	current_period_ = mem_leak_period_enabled;
+}
+
+void MemoryLeakDetector::enable()
+{
+	current_period_ = mem_leak_period_enabled;
+}
+
+void MemoryLeakDetector::disable()
+{
+	current_period_ = mem_leak_period_disabled;
+}
+
+void MemoryLeakDetector::disableAllocationTypeChecking()
+{
+	doAllocationTypeChecking_ = false;
+}
+
+void MemoryLeakDetector::enableAllocationTypeChecking()
+{
+	doAllocationTypeChecking_ = true;
+}
+
+unsigned MemoryLeakDetector::getCurrentAllocationNumber()
+{
+	return allocationSequenceNumber_;
+}
+
+static size_t calculateVoidPointerAlignedSize(size_t size)
+{
+	return (sizeof(void*) - (size % sizeof(void*))) + size;
+}
+
+size_t MemoryLeakDetector::sizeOfMemoryWithCorruptionInfo(size_t size)
+{
+	return calculateVoidPointerAlignedSize(size + memory_corruption_buffer_size);
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetector::getNodeFromMemoryPointer(char* memory, size_t memory_size)
+{
+	return (MemoryLeakDetectorNode*) (void*) (memory + sizeOfMemoryWithCorruptionInfo(memory_size));
+}
+
+void MemoryLeakDetector::storeLeakInformation(MemoryLeakDetectorNode * node, char *new_memory, size_t size, TestMemoryAllocator *allocator, const char *file, int line)
+{
+	node->init(new_memory, allocationSequenceNumber_++, size, allocator, current_period_, file, line);
+	addMemoryCorruptionInformation(node->memory_ + node->size_);
+	memoryTable_.addNewNode(node);
+}
+
+char* MemoryLeakDetector::reallocateMemoryAndLeakInformation(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+	char* new_memory = reallocateMemoryWithAccountingInformation(allocator, memory, size, file, line, allocatNodesSeperately);
+	if (new_memory == NULL) return NULL;
+
+	MemoryLeakDetectorNode *node = createMemoryLeakAccountingInformation(allocator, size, new_memory, allocatNodesSeperately);
+	storeLeakInformation(node, new_memory, size, allocator, file, line);
+	return node->memory_;
+}
+
+void MemoryLeakDetector::invalidateMemory(char* memory)
+{
+  MemoryLeakDetectorNode* node = memoryTable_.retrieveNode(memory);
+  if (node)
+    PlatformSpecificMemset(memory, 0xCD, node->size_);
+}
+
+void MemoryLeakDetector::addMemoryCorruptionInformation(char* memory)
+{
+	memory[0] = 'B';
+	memory[1] = 'A';
+	memory[2] = 'S';
+}
+
+bool MemoryLeakDetector::validMemoryCorruptionInformation(char* memory)
+{
+	return memory[0] == 'B' && memory[1] == 'A' && memory[2] == 'S';
+}
+
+bool MemoryLeakDetector::matchingAllocation(TestMemoryAllocator *alloc_allocator, TestMemoryAllocator *free_allocator)
+{
+	if (alloc_allocator == free_allocator) return true;
+	if (!doAllocationTypeChecking_) return true;
+	return free_allocator->isOfEqualType(alloc_allocator);
+}
+
+void MemoryLeakDetector::checkForCorruption(MemoryLeakDetectorNode* node, const char* file, int line, TestMemoryAllocator* allocator, bool allocateNodesSeperately)
+{
+	if (!matchingAllocation(node->allocator_, allocator))
+		outputBuffer_.reportAllocationDeallocationMismatchFailure(node, file, line, allocator, reporter_);
+	else if (!validMemoryCorruptionInformation(node->memory_ + node->size_))
+		outputBuffer_.reportMemoryCorruptionFailure(node, file, line, allocator, reporter_);
+	else if (allocateNodesSeperately)
+		allocator->freeMemoryLeakNode((char*) node);
+}
+
+char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, bool allocatNodesSeperately)
+{
+	return allocMemory(allocator, size, UNKNOWN, 0, allocatNodesSeperately);
+}
+
+char* MemoryLeakDetector::allocateMemoryWithAccountingInformation(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+	if (allocatNodesSeperately) return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size), file, line);
+	else return allocator->alloc_memory(sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode), file, line);
+}
+
+char* MemoryLeakDetector::reallocateMemoryWithAccountingInformation(TestMemoryAllocator* /*allocator*/, char* memory, size_t size, const char* /*file*/, int /*line*/, bool allocatNodesSeperately)
+{
+	if (allocatNodesSeperately) return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size));
+	else return (char*) PlatformSpecificRealloc(memory, sizeOfMemoryWithCorruptionInfo(size) + sizeof(MemoryLeakDetectorNode));
+}
+
+MemoryLeakDetectorNode* MemoryLeakDetector::createMemoryLeakAccountingInformation(TestMemoryAllocator* allocator, size_t size, char* memory, bool allocatNodesSeperately)
+{
+	if (allocatNodesSeperately) return (MemoryLeakDetectorNode*) (void*) allocator->allocMemoryLeakNode(sizeof(MemoryLeakDetectorNode));
+	else return getNodeFromMemoryPointer(memory, size);
+}
+
+char* MemoryLeakDetector::allocMemory(TestMemoryAllocator* allocator, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+	/* With malloc, it is harder to guarantee that the allocator free is called.
+	 * This is because operator new is overloaded via linker symbols, but malloc just via #defines.
+	 * If the same allocation is used and the wrong free is called, it will deallocate the memory leak information
+	 * without the memory leak detector ever noticing it!
+	 * So, for malloc, we'll allocate the memory separately so we can detect this and give a proper error.
+	 */
+
+	char* memory = allocateMemoryWithAccountingInformation(allocator, size, file, line, allocatNodesSeperately);
+	if (memory == NULL) return NULL;
+	MemoryLeakDetectorNode* node = createMemoryLeakAccountingInformation(allocator, size, memory, allocatNodesSeperately);
+
+	storeLeakInformation(node, memory, size, allocator, file, line);
+	return node->memory_;
+}
+
+void MemoryLeakDetector::removeMemoryLeakInformationWithoutCheckingOrDeallocatingTheMemoryButDeallocatingTheAccountInformation(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
+{
+	MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
+	if (allocatNodesSeperately) allocator->freeMemoryLeakNode( (char*) node);
+}
+
+void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, const char* file, int line, bool allocatNodesSeperately)
+{
+	if (memory == 0) return;
+
+	MemoryLeakDetectorNode* node = memoryTable_.removeNode((char*) memory);
+	if (node == NULL) {
+		outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
+		return;
+	}
+	if (!allocator->hasBeenDestroyed()) {
+		checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
+		allocator->free_memory((char*) memory, file, line);
+	}
+}
+
+void MemoryLeakDetector::deallocMemory(TestMemoryAllocator* allocator, void* memory, bool allocatNodesSeperately)
+{
+	deallocMemory(allocator, (char*) memory, UNKNOWN, 0, allocatNodesSeperately);
+}
+
+char* MemoryLeakDetector::reallocMemory(TestMemoryAllocator* allocator, char* memory, size_t size, const char* file, int line, bool allocatNodesSeperately)
+{
+	if (memory) {
+		MemoryLeakDetectorNode* node = memoryTable_.removeNode(memory);
+		if (node == NULL) {
+			outputBuffer_.reportDeallocateNonAllocatedMemoryFailure(file, line, allocator, reporter_);
+			return NULL;
+		}
+		checkForCorruption(node, file, line, allocator, allocatNodesSeperately);
+	}
+	return reallocateMemoryAndLeakInformation(allocator, memory, size, file, line, allocatNodesSeperately);
+}
+
+void MemoryLeakDetector::ConstructMemoryLeakReport(MemLeakPeriod period)
+{
+	MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(period);
+
+	outputBuffer_.startMemoryLeakReporting();
+
+	while (leak) {
+		outputBuffer_.reportMemoryLeak(leak);
+		leak = memoryTable_.getNextLeak(leak, period);
+	}
+
+	outputBuffer_.stopMemoryLeakReporting();
+}
+
+const char* MemoryLeakDetector::report(MemLeakPeriod period)
+{
+	outputBuffer_.clear();
+	ConstructMemoryLeakReport(period);
+
+	return outputBuffer_.toString();
+}
+
+void MemoryLeakDetector::markCheckingPeriodLeaksAsNonCheckingPeriod()
+{
+	MemoryLeakDetectorNode* leak = memoryTable_.getFirstLeak(mem_leak_period_checking);
+	while (leak) {
+		if (leak->period_ == mem_leak_period_checking) leak->period_ = mem_leak_period_enabled;
+		leak = memoryTable_.getNextLeak(leak, mem_leak_period_checking);
+	}
+}
+
+int MemoryLeakDetector::totalMemoryLeaks(MemLeakPeriod period)
+{
+	return memoryTable_.getTotalLeaks(period);
+}