📄 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 + -