📄 mymem.c
字号:
/*
* CUnit - A Unit testing framework library for C.
* Copyright (C) 2001 Anil Kumar
* Copyright (C) 2004,2005,2006 Anil Kumar, Jerry St.Clair
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* Memory management functions used throughout CUnit.
*
* 13/Oct/2001 Moved some of the generic functions definitions from other
* files to this one so as to use the functions consitently.
* This file is not included in the distribution headers because
* it is used internally by CUnit. (AK)
*
* 18-Jul-2004 New interface, doxygen comments, made local functions &
* constants static, fixed reporting of memory tracking (valid
* vs invalid cycles), restructured memory tracking to detect
* reallocations & multiple deletions. (JDS)
*
* 24-Apr-2005 Changed type of allocated sizes to size_t to avoid
* signed-unsigned mismatch. (JDS)
*/
/** @file
* Memory management & reporting functions (implementation).
*/
/** @addtogroup Framework
@{
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
#include <time.h>
#include "CUnit.h"
#include "MyMem.h"
#ifdef MEMTRACE
#define MAX_FILE_NAME_LENGTH 256
/** Default name for memory dump file. */
static const char* f_szDefaultDumpFileName = "CUnit-Memory-Dump.xml";
/**< Default name for memory dump file. */
#ifdef CUNIT_BUILD_TESTS
/** For testing use (only) to simulate memory exhaustion -
* if CU_FALSE, allocation requests will always fail and return NULL.
*/
static CU_BOOL f_bTestCunitMallocActive = CU_TRUE;
#endif
/** Structure holding the details of a memory allocation/deallocation event. */
typedef struct mem_event {
size_t Size;
unsigned int AllocLine;
char AllocFilename[MAX_FILE_NAME_LENGTH];
unsigned int DeallocLine;
char DeallocFilename[MAX_FILE_NAME_LENGTH];
struct mem_event* pNext;
} MEMORY_EVENT;
typedef MEMORY_EVENT* PMEMORY_EVENT;
#define NOT_ALLOCATED 0
#define NOT_DELETED 0
/** Structure holding the details of a memory node having allocation/deallocation events. */
typedef struct mem_node {
void* pLocation;
unsigned int EventCount;
PMEMORY_EVENT pFirstEvent;
struct mem_node* pNext;
} MEMORY_NODE;
typedef MEMORY_NODE* PMEMORY_NODE;
static PMEMORY_NODE f_pMemoryTrackerHead = NULL; /**< Head of double-linked list of memory nodes. */
static unsigned int f_nMemoryNodes = 0; /**< Counter for memory nodes created. */
/*------------------------------------------------------------------------*/
/** Locate the memory node for the specified memory location (returns NULL if none). */
static PMEMORY_NODE find_memory_node(void* pLocation)
{
PMEMORY_NODE pMemoryNode = f_pMemoryTrackerHead;
while (NULL != pMemoryNode) {
if (pLocation == pMemoryNode->pLocation) {
break;
}
pMemoryNode = pMemoryNode->pNext;
}
return pMemoryNode;
}
/*------------------------------------------------------------------------*/
/** Create a new memory node for the specified memory location. */
static PMEMORY_NODE create_memory_node(void* pLocation)
{
PMEMORY_NODE pTempNode = NULL;
PMEMORY_NODE pMemoryNode = find_memory_node(pLocation);
/* a memory node for pLocation should not exist yet */
if (NULL == pMemoryNode) {
pMemoryNode = (PMEMORY_NODE)malloc(sizeof(MEMORY_NODE));
assert(NULL != pMemoryNode);
pMemoryNode->pLocation = pLocation;
pMemoryNode->EventCount = 0;
pMemoryNode->pFirstEvent = NULL;
pMemoryNode->pNext = NULL;
/* add new node to linked list */
pTempNode = f_pMemoryTrackerHead;
if (NULL == pTempNode) {
f_pMemoryTrackerHead = pMemoryNode;
}
else {
while (NULL != pTempNode->pNext) {
pTempNode = pTempNode->pNext;
}
pTempNode->pNext = pMemoryNode;
}
++f_nMemoryNodes;
}
return pMemoryNode;
}
/*------------------------------------------------------------------------*/
/** Add a new memory event having the specified parameters. */
static PMEMORY_EVENT add_memory_event(PMEMORY_NODE pMemoryNode,
size_t size,
unsigned int alloc_line,
const char* alloc_filename)
{
PMEMORY_EVENT pMemoryEvent = NULL;
PMEMORY_EVENT pTempEvent = NULL;
assert (NULL != pMemoryNode);
/* create and set up the new event */
pMemoryEvent = malloc(sizeof(MEMORY_EVENT));
assert(NULL != pMemoryEvent);
pMemoryEvent->Size = size;
pMemoryEvent->AllocLine = alloc_line;
strncpy(pMemoryEvent->AllocFilename, alloc_filename, (size_t) MAX_FILE_NAME_LENGTH-1);
pMemoryEvent->AllocFilename[MAX_FILE_NAME_LENGTH-1] = (char)0;
pMemoryEvent->DeallocLine = NOT_DELETED;
pMemoryEvent->DeallocFilename[0] = (char)0;
pMemoryEvent->pNext = NULL;
/* add the new event to the end of the linked list */
pTempEvent = pMemoryNode->pFirstEvent;
if (NULL == pTempEvent) {
pMemoryNode->pFirstEvent = pMemoryEvent;
}
else {
while (NULL != pTempEvent->pNext) {
pTempEvent = pTempEvent->pNext;
}
pTempEvent->pNext = pMemoryEvent;
}
++pMemoryNode->EventCount;
return pMemoryEvent;
}
/*------------------------------------------------------------------------*/
/** Record memory allocation event. */
static PMEMORY_NODE allocate_memory(size_t nSize,
void* pLocation,
unsigned int uiAllocationLine,
const char* szAllocationFile)
{
PMEMORY_NODE pMemoryNode = NULL;
/* attempt to locate an existing record for this pLocation */
pMemoryNode = find_memory_node(pLocation);
/* pLocation not found - create a new event record */
if (NULL == pMemoryNode) {
pMemoryNode = create_memory_node(pLocation);
}
/* add the new event record */
add_memory_event(pMemoryNode, nSize, uiAllocationLine, szAllocationFile);
return pMemoryNode;
}
/*------------------------------------------------------------------------*/
/** Record memory deallocation event. */
static void deallocate_memory(void* pLocation, unsigned int uiDeletionLine, const char* szDeletionFileName)
{
PMEMORY_NODE pMemoryNode = NULL;
PMEMORY_EVENT pTempEvent = NULL;
assert(0 != uiDeletionLine);
assert(NULL != szDeletionFileName);
/* attempt to locate an existing record for this pLocation */
pMemoryNode = find_memory_node(pLocation);
/* if no entry, then an unallocated pointer was freed */
if (NULL == pMemoryNode) {
pMemoryNode = create_memory_node(pLocation);
pTempEvent = add_memory_event(pMemoryNode, 0, NOT_ALLOCATED, "");
}
else {
/* there should always be at least 1 event for an existing memory node */
assert(NULL != pMemoryNode->pFirstEvent);
/* locate last memory event for this pLocation */
pTempEvent = pMemoryNode->pFirstEvent;
while (NULL != pTempEvent->pNext) {
pTempEvent = pTempEvent->pNext;
}
/* if pointer has already been freed, create a new event for double deletion */
if (NOT_DELETED != pTempEvent->DeallocLine) {
pTempEvent = add_memory_event(pMemoryNode, pTempEvent->Size, NOT_ALLOCATED, "");
}
}
pTempEvent->DeallocLine = uiDeletionLine;
strncpy(pTempEvent->DeallocFilename, szDeletionFileName, MAX_FILE_NAME_LENGTH-1);
pTempEvent->DeallocFilename[MAX_FILE_NAME_LENGTH-1] = (char)0;
}
/*------------------------------------------------------------------------*/
/** Custom calloc function with memory event recording. */
void* CU_calloc(size_t nmemb, size_t size, unsigned int uiLine, const char* szFileName)
{
void* pVoid = NULL;
#ifdef CUNIT_BUILD_TESTS
if (CU_FALSE == f_bTestCunitMallocActive) {
return NULL;
}
#endif
pVoid = calloc(nmemb, size);
if (NULL != pVoid) {
allocate_memory(nmemb * size, pVoid, uiLine, szFileName);
}
return pVoid;
}
/*------------------------------------------------------------------------*/
/** Custom malloc function with memory event recording. */
void* CU_malloc(size_t size, unsigned int uiLine, const char* szFileName)
{
void* pVoid = NULL;
#ifdef CUNIT_BUILD_TESTS
if (CU_FALSE == f_bTestCunitMallocActive) {
return NULL;
}
#endif
pVoid = malloc(size);
if (NULL != pVoid) {
allocate_memory(size, pVoid, uiLine, szFileName);
}
return pVoid;
}
/*------------------------------------------------------------------------*/
/** Custom free function with memory event recording. */
void CU_free(void *ptr, unsigned int uiLine, const char* szFileName)
{
deallocate_memory(ptr, uiLine, szFileName);
free(ptr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -