summaryrefslogtreecommitdiff
path: root/test/spass/memory.c
diff options
context:
space:
mode:
authorGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2010-03-03 12:34:43 +0000
committerGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2010-03-03 12:34:43 +0000
commit6c196ec8a41d6ed506c133c8b33dba9684f9a7a6 (patch)
tree4e1422ea2a810520d0d9b0fbb78c0014ba9f8443 /test/spass/memory.c
parent93d89c2b5e8497365be152fb53cb6cd4c5764d34 (diff)
Updated raytracer test. Added SPASS test.
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1271 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'test/spass/memory.c')
-rw-r--r--test/spass/memory.c1595
1 files changed, 1595 insertions, 0 deletions
diff --git a/test/spass/memory.c b/test/spass/memory.c
new file mode 100644
index 0000000..a785515
--- /dev/null
+++ b/test/spass/memory.c
@@ -0,0 +1,1595 @@
+/**************************************************************/
+/* ********************************************************** */
+/* * * */
+/* * DYNAMIC MEMORY MANAGEMENT MODULE * */
+/* * * */
+/* * $Module: MEMORY * */
+/* * * */
+/* * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 * */
+/* * MPI fuer Informatik * */
+/* * * */
+/* * This program is free software; you can redistribute * */
+/* * it and/or modify it under the terms of the GNU * */
+/* * General Public License as published by the Free * */
+/* * Software Foundation; either version 2 of the License, * */
+/* * or (at your option) any later version. * */
+/* * * */
+/* * This program 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 General Public * */
+/* * License for more details. * */
+/* * * */
+/* * You should have received a copy of the GNU General * */
+/* * Public License along with this program; if not, write * */
+/* * to the Free Software Foundation, Inc., 59 Temple * */
+/* * Place, Suite 330, Boston, MA 02111-1307 USA * */
+/* * * */
+/* * * */
+/* $Revision: 21527 $ * */
+/* $State$ * */
+/* $Date: 2005-04-24 21:10:28 -0700 (Sun, 24 Apr 2005) $ * */
+/* $Author: duraid $ * */
+/* * * */
+/* * Contact: * */
+/* * Christoph Weidenbach * */
+/* * MPI fuer Informatik * */
+/* * Stuhlsatzenhausweg 85 * */
+/* * 66123 Saarbruecken * */
+/* * Email: weidenb@mpi-sb.mpg.de * */
+/* * Germany * */
+/* * * */
+/* ********************************************************** */
+/**************************************************************/
+
+
+/* $RCSfile$ */
+
+#include "memory.h"
+
+unsigned int memory_PAGESIZE; /* size of a page */
+long memory_MAXMEM; /* amount of memory available for allocation */
+static int memory__EOF = EOF; /* internal "End Of Memory" marker */
+unsigned long memory_NEWBYTES; /* number of allocated bytes */
+unsigned long memory_FREEDBYTES; /* number of freed bytes */
+
+const unsigned int memory_ALIGN = sizeof(POINTER);
+/* Crucial: hardware must support access to words
+ of size POINTER.
+*/
+
+#ifdef CHECK
+unsigned int memory_LEFTTAG; /* size of left debug mark */
+unsigned int memory_OFFSET; /* alignment-correct size of left debug mark */
+unsigned int memory_MARKSIZE; /* total size of debug marks */
+
+BOOL memory_MANAGEMENT_INITIALIZED = FALSE;
+
+#else /* CHECK not defined */
+unsigned int memory_MARKSIZE = 0;
+unsigned int memory_OFFSET = 0;
+#endif /* CHECK */
+
+const unsigned int memory_MAGICMALLOC = 1; /* "block allocated" marker */
+const unsigned int memory_MAGICFREE = 2; /* "block freed" marker */
+
+/* Internal array of resources for different block sizes */
+/* ... + 1 to support odd values for memory__SHAREDPAGES like 7 */
+static MEMORY_RESOURCE memory_PAGES[memory__DYNMAXSIZE/memory__SHAREDPAGES + 1];
+
+
+/* Resources for all administrated block sizes */
+MEMORY_RESOURCE * memory_ARRAY[memory__DYNMAXSIZE];
+
+/* double linked list for administering blocks of memory
+ whose size is greater or equal to memory__DYNMAXSIZE.
+*/
+MEMORY_BIGBLOCKHEADER memory_BIGBLOCKS = NULL;
+
+/**************************************************************/
+/* ********************************************************** */
+/* * * */
+/* * INITIALIZATION * */
+/* * * */
+/* ********************************************************** */
+/**************************************************************/
+
+#ifdef CHECK
+static BOOL memory_ManagementInitialized(void)
+/**********************************************************
+ INPUT : None.
+ RETURNS: TRUE if memory management is already initialized,
+ else FALSE.
+ SUMMARY: Checks if memory_Init was called.
+**********************************************************/
+{
+ return memory_MANAGEMENT_INITIALIZED;
+}
+#endif /* CHECK */
+
+void memory_Init(long Maxmem)
+/*************************************************************
+ INPUT : The maximal amount of memory available in bytes
+ for the memory module; if Maxmem < 0 the module
+ allocates as much memory as available from the
+ system.
+ RETURNS: None.
+ SUMMARY: Initializes the memory management. It has to be
+ called before you can perform any module operation.
+ This function automatically increases the default
+ page size if it is too small for two objects of
+ size memory__DYNMAXSIZE.
+*************************************************************/
+{
+ int i;
+ int extra; /* size of internally used space on each page */
+
+ memory_FREEDBYTES = 0; /* set total number of freed bytes to zero */
+ memory_NEWBYTES = 0; /* set total number of allocated bytes to zero */
+
+ /* set the size of a page we allocate from the operating system */
+ memory_PAGESIZE = memory__DEFAULTPAGESIZE;
+
+#ifdef CHECK
+
+ /* Test if memory management has already been initialized */
+
+ if (!memory_ManagementInitialized()) {
+ /* if that is not the case, set check variable to TRUE */
+ memory_MANAGEMENT_INITIALIZED = TRUE;
+ }
+ else {
+ /* otherwise the user is trying initialize it for a
+ second time, so print an error and exit.
+ */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Init:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Trying to initialize memory management");
+ misc_UserErrorReport(" for a second time.\n");
+ misc_FinishUserErrorReport();
+ }
+
+ /* Calculate the size of debug marks */
+ memory_LEFTTAG = sizeof(MEMORY_INFONODE) + sizeof(unsigned int);
+
+ if ((sizeof(MEMORY_INFONODE) + sizeof(unsigned int)) % memory_ALIGN == 0) {
+ memory_OFFSET = memory_LEFTTAG;
+ }
+ else {
+ memory_OFFSET = memory_LEFTTAG + memory_ALIGN
+ - (memory_LEFTTAG % memory_ALIGN);
+ }
+
+ if ((sizeof(unsigned int) % memory_ALIGN) == 0) {
+ memory_MARKSIZE = memory_OFFSET + sizeof(unsigned int);
+ }
+ else {
+ memory_MARKSIZE = memory_OFFSET + sizeof(unsigned int) + memory_ALIGN
+ - (sizeof(unsigned int) % memory_ALIGN);
+ }
+#endif
+
+ /* Calculate the size of internally used space on each page */
+ /* extra: One pointer for chaining pages, one for EOF (+ marksize) */
+ extra = 2*sizeof(POINTER) + memory_MARKSIZE;
+
+
+ /* Test whether page size is reasonable with respect
+ to dynamic allocation threshold
+ */
+ while (memory_PAGESIZE < (2*(memory__DYNMAXSIZE + memory_MARKSIZE) + extra)) {
+ /* Minimum two objects per allocated page */
+ memory_PAGESIZE += memory__DEFAULTPAGESIZE/2;
+ }
+
+ /* Set amount of memory available to the module for allocation */
+ if (Maxmem <= 0) {
+ /* unlimited (limited only by the operating system) */
+ memory_MAXMEM = memory__UNLIMITED;
+ }
+ else {
+ /* Maxmem bytes */
+ memory_MAXMEM = Maxmem;
+ }
+
+ /* Initialize memory_ARRAY and memory_RESOURCEs */
+ for (i=1; i<memory__DYNMAXSIZE; i++) {
+ MEMORY_RESOURCE *CurrentResource;
+ int TotalSize;
+
+ /* Map memory_ARRAY[i] to appropriate Resource */
+ memory_ARRAY[i] = &memory_PAGES[(i-1)/memory__SHAREDPAGES];
+
+ CurrentResource = memory_ARRAY[i];
+
+ CurrentResource->free = &memory__EOF; /* no blocks freed */
+ CurrentResource->next = &memory__EOF; /* no blocks allocated */
+ CurrentResource->end_of_page = &memory__EOF; /* no (end of) page */
+ CurrentResource->page = &memory__EOF; /* no page allocated */
+
+ /* Size of a properly aligned block of requested size i */
+ CurrentResource->aligned_size = memory_CalculateRealBlockSize(i);
+
+ /* Total block size including debug marks */
+ CurrentResource->total_size = memory_MARKSIZE
+ + CurrentResource->aligned_size;
+
+ TotalSize = CurrentResource->total_size;
+
+ /* last blockīs offset */
+ CurrentResource->offset =
+ ((memory_PAGESIZE-extra)/TotalSize)*TotalSize
+ + sizeof(POINTER) + memory_OFFSET;
+ }
+}
+
+
+void memory_Restrict(long Maxmem)
+/*************************************************************
+ INPUT : The maximal amount of memory available for further
+ allocation (in bytes); if Maxmem < 0 future
+ allocations are unrestricted.
+ RETURNS: None.
+ SUMMARY: Sets the maximal amount of memory available for
+ future allocations. If the user tries to allocate
+ more memory, the module displays an error message
+ and terminates the program by calling the exit()
+ function.
+*************************************************************/
+{
+ /* Reset the maximum amount of memory available */
+ if (Maxmem <= 0) {
+ /* unlimited */
+ memory_MAXMEM = memory__UNLIMITED;
+ }
+ else {
+ /* Maxmem bytes */
+ memory_MAXMEM = Maxmem;
+ }
+}
+
+/**************************************************************/
+/* ********************************************************** */
+/* * * */
+/* * CHECK CODE * */
+/* * * */
+/* ********************************************************** */
+/**************************************************************/
+
+#ifdef CHECK
+static void memory_CheckIfModuleIsInitialized(const char * Function,
+ const char * File,
+ unsigned short int Line)
+/********************************************************
+ INPUT : The name of the function that requests the
+ check, the name of the file and the line,
+ where the requesting function was called, and
+ the line.
+ RETURNS: None.
+ SUMMARY: Checks if the memory management module has
+ been properly initialized. You need to
+ initialize the module by calling memory_Init
+ before you use any functions from the module.
+ If the check fails, this function prints an
+ error message and exits the application.
+*********************************************************/
+{
+ if (!memory_ManagementInitialized()) {
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In %s:", Function);
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Memory management is not initialized.");
+ misc_UserErrorReport("\n You have to call memory_Init()");
+ misc_UserErrorReport(" before you can use memory management functions.\n");
+ misc_UserErrorReport("\n Error occurred in %s", Function);
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+ misc_FinishUserErrorReport();
+ }
+}
+
+static void memory_CheckIfPointerIsAlreadyFreed(POINTER Pointer,
+ const char * Function,
+ const char * File,
+ unsigned short int Line)
+/********************************************************
+ INPUT : The pointer to be checked, the name of the
+ function that requests the check, the name of
+ the file and the line, where the requesting
+ function was called, and the line.
+ RETURNS: None.
+ SUMMARY: Checks if the pointer has already been freed.
+ If the check fails, this function prints an
+ error message and exits the application.
+*********************************************************/
+{
+ if ( memory_GetBlockStatus(Pointer) == memory_MAGICFREE) {
+ MEMORY_INFO Info; /* blockīs debug information */
+
+ Info = (MEMORY_INFO) ((char *) Pointer - memory_OFFSET);
+
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In %s:", Function);
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d.",
+ Pointer, Info->mallocInFile, Info->mallocAtLine);
+ misc_UserErrorReport("\n It has already been freed in file %s at line %d.",
+ Info->freeInFile, Info->freeAtLine);
+ misc_UserErrorReport("\n Size of memory block is %d bytes.",
+ memory_GetBlockSize(Pointer));
+ misc_UserErrorReport("\n Error occurred in %s", Function);
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+ misc_FinishUserErrorReport();
+ }
+}
+
+static void memory_CheckPointer(POINTER Pointer, unsigned int Size)
+/*********************************************************
+ INPUT : A pointer to a block of memory, and its size.
+ RETURNS: Nothing.
+ SUMMARY: Checks whether a pointer points to a valid
+ block of memory.
+
+ This function performs the following tests:
+
+ Is Pointer a NULL pointer?
+
+ Is Size equal to zero?
+
+ Is the Pointer alignment correct?
+
+ Did someone write over the memory block
+ boundaries?
+
+ Is Size still correct?
+
+ If Size is greater than memory__DYNMAXSIZE:
+ Is it properly administrated by the module?
+
+ If the memory block was freed: Did someone
+ write to it after deallocation?
+*********************************************************/
+{
+
+ MEMORY_INFO Info;
+ unsigned int BlockSize, RealBlockSize, BlockStatus;
+
+ Info = (MEMORY_INFO) ((char *) Pointer - memory_OFFSET);
+
+ RealBlockSize = memory_LookupRealBlockSize(Size);
+
+ if (Pointer == NULL) {
+ /* NULL pointers must not be dereferenced */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error. Pointer is a NULL pointer.\n");
+ misc_FinishUserErrorReport();
+ }
+
+
+ if (Size == 0) {
+ /* We donīt allocate 0 byte sized blocks */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p points to a block of memory", Pointer);
+ misc_UserErrorReport(" with size 0.\n");
+ misc_FinishUserErrorReport();
+ }
+
+ if ((unsigned long)Pointer % (unsigned long)memory_ALIGN){
+ /* we expect all pointers to be correctly aligned */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p is not a legal pointer.\n", Pointer);
+ misc_FinishUserErrorReport();
+ }
+
+ /* BlockStatus and BlockSize are initialized after
+ we can be sure Pointer is properly aligned.
+ */
+
+ BlockStatus = memory_GetBlockStatus(Pointer);
+ BlockSize = memory_GetBlockSize(Pointer);
+
+ if (BlockStatus != memory_MAGICMALLOC
+ && BlockStatus != memory_MAGICFREE) {
+
+ /* we expect block status to be either
+ memory_MAGICMALLOC or memory_MAGICFREE.
+ Other values might result from overwriting,
+ trying to return an unallocated block,
+ or trying to return a block allocated with
+ another allocator.
+ */
+
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p was not (de)allocated by the module,",
+ Pointer);
+ misc_UserErrorReport("\n or the memory block was corrupted.\n");
+ misc_FinishUserErrorReport();
+ }
+
+ if (BlockStatus == memory_MAGICMALLOC) {
+ if (BlockSize != Size) {
+
+ /* we expect block size in a blockīs debug
+ information and given block size to match.
+ */
+
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p was apparently allocated for",
+ Pointer);
+ misc_UserErrorReport(" a block of size %d,",
+ BlockSize);
+ misc_UserErrorReport("\n but it is expected to be a block of size %d.",
+ Size);
+ misc_UserErrorReport("\n Probably the memory block was corrupted.\n");
+ misc_FinishUserErrorReport();
+
+ /* since the left dog tag seems to be corrupted we can not safely assume
+ that our memory info structure is still valid so we can't print it*/
+ }
+
+ if ((Size % memory_ALIGN) || (Size % memory__SHAREDPAGES)) {
+ /* check the fillbytes between used storage
+ and dog tag for overwriting */
+ char * ptr, * limit;
+
+ limit = (char *)Pointer + RealBlockSize;
+
+ for (ptr = (char *)Pointer + Size; ptr < limit; ptr++) {
+ if (*ptr != memory__FREESHREDDER) {
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d,",
+ Pointer, Info->mallocInFile, Info->mallocAtLine);
+ misc_UserErrorReport("\n for a block of size %d.",
+ BlockSize);
+ misc_UserErrorReport("\n The memory block was corrupted.\n");
+ misc_FinishUserErrorReport();
+ }
+ }
+ }
+ }
+
+ if (Size >= memory__DYNMAXSIZE) {
+ /* we expect big blocks to be correctly linked */
+ MEMORY_BIGBLOCKHEADER BigBlockHeader;
+
+ BigBlockHeader = (MEMORY_BIGBLOCKHEADER) ((char *) Pointer - memory_OFFSET
+ - sizeof(MEMORY_BIGBLOCKHEADERNODE));
+
+ /* this test might crash the program
+ if something is wrong with the pointers,
+ so you may not get a message every time.
+ */
+ if (((BigBlockHeader->previous != NULL)
+ && (BigBlockHeader->previous->next != BigBlockHeader))
+ || ((BigBlockHeader->previous == NULL)
+ && (memory_BIGBLOCKS != BigBlockHeader))
+ || ((BigBlockHeader->next != NULL)
+ && (BigBlockHeader->next->previous != BigBlockHeader))) {
+
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p was not allocated by the module,",
+ Pointer);
+ misc_UserErrorReport("\n or the memory block was corrupted.\n");
+ misc_FinishUserErrorReport();
+ }
+ }
+
+ if (BlockStatus == memory_MAGICFREE) {
+ /* test if someone wrote over freed memory */
+ char * ptr, * limit;
+
+ limit = (char *)Pointer + RealBlockSize;
+
+ for (ptr = (char *)Pointer + sizeof(POINTER); ptr < limit ; ptr++){
+ /* first sizeof(POINTER) bytes are reserved for the
+ pointer to the next freed block in the list. All
+ other bytes in the block should still have the value
+ of memory__FREESHREDDER
+ */
+ if (*ptr != memory__FREESHREDDER) {
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_CheckPointer:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Pointer %p was allocated in file %s at line %d",
+ Pointer, Info->mallocInFile, Info->mallocAtLine);
+ misc_UserErrorReport("\n for a block of size %d",BlockSize);
+ misc_UserErrorReport("\n and freed in file %s at line %d.",
+ Info->freeInFile, Info->freeAtLine);
+ misc_UserErrorReport("\n The memory block was used after deallocation.\n");
+ misc_FinishUserErrorReport();
+ }
+ }
+ }
+}
+
+void memory_CheckFree(POINTER Freepointer, unsigned int Size,
+ unsigned int RealBlockSize, const char * File,
+ unsigned short int Line)
+/**********************************************************
+ INPUT : The pointer to be freed, the size of the block
+ it is supposed to point to, the real size of
+ that block, the file and line where memory_Free
+ was called.
+ RETURNS: None.
+ SUMMARY: Checks if memory management was initialized,
+ the given pointer is legal, and not freed
+ already. It also zeroes the freed memory, and
+ sets the block's debug and administration
+ information.
+**********************************************************/
+{
+ MEMORY_INFO Info; /* blockīs debug information */
+
+ /* Check if memory management was initialized */
+ memory_CheckIfModuleIsInitialized("memory_Free", File, Line);
+
+ /* Check if given pointer is legal */
+ memory_CheckPointer(Freepointer, Size);
+
+ /* Check if current pointer is being freed for a second time */
+ memory_CheckIfPointerIsAlreadyFreed(Freepointer, "memory_Free", File, Line);
+
+ /* Set all bytes to zero, so we can detect overwriting of freed memory */
+ memset (Freepointer, memory__FREESHREDDER, RealBlockSize);
+
+ /* Get current blockīs debug information */
+ Info = (MEMORY_INFO) ((char *) Freepointer - memory_OFFSET);
+
+ /* Set blockīs debug and administration information */
+ memory_SetInfo(Info,Info->mallocInFile, Info->mallocAtLine, File, Line);
+ memory_SetBlockStatusAndSize(Freepointer, memory_MAGICFREE, Size);
+}
+#endif /* CHECK */
+
+/**************************************************************/
+/* ********************************************************** */
+/* * * */
+/* * MALLOC * */
+/* * * */
+/* ********************************************************** */
+/**************************************************************/
+
+#ifdef NO_MEMORY_MANAGEMENT
+
+POINTER memory_Malloc(unsigned int Bytes)
+{
+ char *mem; /* pointer to memory block obtained from malloc */
+
+ /* Pass the call through to compilerīs malloc */
+ mem = (char *)malloc(Bytes);
+
+ /* If malloc fails print an error message and exit */
+ if (mem == NULL) {
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Malloc:");
+ misc_UserErrorReport("\n Memory Error. Out of memory.\n");
+ misc_FinishUserErrorReport();
+ }
+
+ return mem;
+}
+
+#else
+
+#ifdef CHECK
+POINTER memory_MallocIntern(unsigned int Bytes,
+ const char * File,
+ unsigned short int Line)
+#else
+POINTER memory_Malloc(unsigned int Bytes)
+#endif
+/********************************************************
+ INPUT : The size of the requested memory block.
+ RETURNS: A pointer to a block of <Bytes> bytes.
+ SUMMARY: Allocates a memory block of requested length.
+ EXCEPT : Trying to allocate 0 bytes, violating a memory
+ restriction, or running out of system memory
+ cause the function to print an error message and
+ call exit().
+*********************************************************/
+{
+ char *NewMemory; /* pointer to allocated memory */
+
+ MEMORY_RESOURCE *Resource; /* current page resource,
+ required if we do not allocate
+ a big block */
+
+#ifdef CHECK
+ MEMORY_INFO NewInfo; /* Storage for file and line
+ of allocation */
+#endif
+
+
+#ifdef CHECK
+ /* Is the module initialized? */
+ memory_CheckIfModuleIsInitialized("memory_Malloc", File, Line);
+
+ /* Is it a request for a block of zero bytes? */
+ if (Bytes == 0) {
+ /* The latest draft for the ANSI C 9X standard says in section 7.20.3:
+
+ "If the size of the space requested is zero, the behavior is
+ implementation-defined: either a null pointer is returned, or
+ the behavior is as if the size were some nonzero value,
+ except that the pointer shall not be used to access an object."
+
+ We have decided to print an error and exit upon such requests
+ since they are often originated by a bug.
+
+ Nonstandard but hopefully helpful.
+ */
+
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Malloc:");
+ misc_UserErrorReport("\n Memory Error. Tried to allocate 0 Bytes!");
+ misc_UserErrorReport("\n Error occurred in memory_Malloc");
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+ misc_FinishUserErrorReport();
+ }
+#endif
+
+ /* If it is a big block, then it has to be
+ administrated in a special way
+ */
+ if (Bytes >= memory__DYNMAXSIZE) {
+ unsigned int RealBigBlockSize; /* real block size including
+ padding,header
+ and debug marks */
+
+ /* This is what a big block looks like:
+
+ --------------------------------------------------------------------
+ | MEMORY_BIGBLOCKHEADERNODE | debug marks | char * | debug marks |
+ | previous and next big block |in debug mode| block |in debug mode|
+ --------------------------------------------------------------------
+ */
+
+
+ /* Calculate the real size of the big block,
+ from the size of administration information,
+ the size of debug marks and the requested block size
+ */
+
+ RealBigBlockSize = sizeof(MEMORY_BIGBLOCKHEADERNODE) +
+ memory_MARKSIZE + memory_CalculateRealBlockSize(Bytes);
+
+ /* Check for violation of maximum allocation limit */
+ if (memory_MAXMEM >= 0) {
+ /* there is a maximum allocation limit,
+ letīs see if there is enough left
+ */
+ if ((unsigned int)memory_MAXMEM < RealBigBlockSize) {
+ /* if it is not print an error message and exit */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Malloc:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Terminated by user given memory restriction,\n");
+ misc_UserErrorReport("\n while trying to allocate %lu bytes.\n",
+ RealBigBlockSize);
+ misc_UserErrorReport("\n Maximum amount of memory");
+ misc_UserErrorReport(" left for allocation is %l bytes.\n",
+ memory_MAXMEM);
+#ifdef CHECK
+ misc_UserErrorReport("\n Error occurred in memory_Malloc");
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+#endif
+ misc_FinishUserErrorReport();
+ }
+ else
+ /* otherwise subtract the real block size
+ from the amount of memory available for
+ allocation
+ */
+ memory_MAXMEM -= RealBigBlockSize;
+ }
+
+ /* allocate a fresh block of memory via a call to malloc */
+ NewMemory = (char *)malloc(RealBigBlockSize);
+
+ /* Check if allocation was successful */
+ if (NewMemory != NULL) {
+
+ /* if it was, then administrate the fresh block:
+ insert it into the big block list. The list
+ is double linked for fast deletion
+ */
+
+ MEMORY_BIGBLOCKHEADER NewBigBlock; /* new blockīs administration
+ information */
+
+ /* insert the fresh block as the first list element */
+ NewBigBlock = (MEMORY_BIGBLOCKHEADER) NewMemory;
+ NewBigBlock->next = memory_BIGBLOCKS;
+ NewBigBlock->previous = NULL;
+
+ /* if there are already elements in the big block list,
+ change the first elementīs pointer to the previous block
+ to point to the fresh blockīs administration information
+ */
+ if (memory_BIGBLOCKS != NULL) {
+ memory_BIGBLOCKS->previous = NewBigBlock;
+ }
+
+ /* reset the big block list pointer to point to the fresh block */
+ memory_BIGBLOCKS = NewBigBlock;
+
+ /* skip the administration information */
+ NewMemory += sizeof(MEMORY_BIGBLOCKHEADERNODE);
+
+#ifdef CHECK
+ /* set the debug information address */
+ NewInfo = (MEMORY_INFO) NewMemory;
+
+ /* skip left debug mark */
+ NewMemory += memory_OFFSET;
+#endif
+
+ /* add blockīs real size to the total sum of allocated bytes */
+ memory_NEWBYTES += RealBigBlockSize;
+ }
+ else {
+ /* NewMemory == NULL.
+ malloc could not allocate a memory block of required size,
+ so we print an error message and exit
+ */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_MallocIntern:");
+ misc_UserErrorReport("\n Memory Error. Out of memory.");
+ misc_UserErrorReport("\n Failed to allocate %d bytes.\n",
+ RealBigBlockSize);
+#ifdef CHECK
+ misc_UserErrorReport("\n Error occurred in memory_Malloc");
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+#endif
+ misc_FinishUserErrorReport();
+ }
+ }
+ else {
+ /* Bytes < memory__DYNMAXSIZE.
+ A memory request for a manageable size
+ */
+
+ /* Initialize the memory resource for the given size */
+ Resource = memory_ARRAY[Bytes];
+
+
+ /* Check if there are freed blocks of that size */
+ if (*((int *)Resource->free) != EOF) {
+
+ /* if that is the case, then use an already freed block */
+
+ NewMemory = (char *) Resource->free;
+
+ /* update the free blocks list for that size */
+ Resource->free = *((POINTER *)(NewMemory));
+
+ /* subtract blockīs total size from the sum of freed bytes */
+ memory_FREEDBYTES -= Resource->total_size;
+
+#ifdef CHECK
+ /* calculate the address of the blockīs debug information */
+ NewInfo = (MEMORY_INFO) ((char*) NewMemory - memory_OFFSET);
+
+ /* Check if the block has been used after deallocation */
+ memory_CheckPointer(NewMemory, Bytes);
+#endif
+ }
+ else {
+ /* there are no already freed blocks of that size */
+
+ /* Check if there is enough space left on current page */
+ if (Resource->next != Resource->end_of_page) {
+
+ /* if that is the case, then use a fresh block from current page */
+ NewMemory = (char *)Resource->next;
+
+ /* update the pointer to the next usable block */
+ Resource->next = NewMemory + Resource->total_size;
+
+ /* add blockīs total size to the sum of allocated bytes */
+ memory_NEWBYTES += Resource->total_size;
+
+#ifdef CHECK
+ /* Check if the fresh blockīs address is sane */
+ if ((char *)NewMemory > (char *) Resource->end_of_page) {
+ /* if it is not, then we have detected an internal error
+ in the module itself. Oops! So we print an error message
+ and abort, hoping that the core dump will enable us to
+ trace the error back to its origin
+ */
+ misc_StartErrorReport();
+ misc_ErrorReport("\n In memory_Malloc:");
+ misc_ErrorReport("\n Memory Error. Address overflow %d.",Bytes);
+ misc_ErrorReport("\n Error occurred in memory_Malloc");
+ misc_ErrorReport(" called from file %s at line %d.\n", File, Line);
+ misc_FinishErrorReport();
+ }
+
+ /* if all is well, we initialize the pointer to fresh blockīs
+ debug information
+ */
+ NewInfo = (MEMORY_INFO)((char*) NewMemory - memory_OFFSET);
+#endif
+
+ }
+ else {
+ /* Check for violation of maximum allocation limit */
+ if (memory_MAXMEM >=0) {
+ /* there is a maximum allocation limit,
+ letīs see if there is enough left
+ */
+ if ((unsigned int)memory_MAXMEM < memory_PAGESIZE) {
+ /* if it is not, then print an error message and exit */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Malloc:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Terminated by user given memory restriction.\n");
+#ifdef CHECK
+ misc_UserErrorReport("\n Error occurred in memory_Malloc");
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+#endif
+ misc_FinishUserErrorReport();
+ }
+ else {
+ /* otherwise subtract the page size from the limit */
+ memory_MAXMEM -= memory_PAGESIZE;
+ }
+ }
+
+ /* try to allocate a new page via malloc */
+ NewMemory=(char *)malloc(memory_PAGESIZE);
+
+ /* check if allocation was successful */
+ if (NewMemory == NULL) {
+ /* if it wasnīt print an error message and exit */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Malloc:");
+ misc_UserErrorReport("\n Memory Error.");
+ misc_UserErrorReport(" Terminated, ran out of system memory.\n");
+#ifdef CHECK
+ misc_UserErrorReport("\n Error occurred in memory_Malloc");
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+#endif
+ misc_FinishUserErrorReport();
+ }
+
+ /* otherwise administrate the fresh page,
+ i.e insert it as the first element of the
+ page list for the given size
+ */
+ *((POINTER *)NewMemory) = Resource->page;
+ Resource->page = NewMemory;
+
+ /* add blockīs total size to the sum of allocated bytes */
+ memory_NEWBYTES += Resource->total_size;
+
+ /* set the end of page pointer for the fresh page */
+ Resource->end_of_page = (char *) NewMemory + Resource->offset;
+
+ /* skip the page list */
+ NewMemory += sizeof(POINTER);
+
+#ifdef CHECK
+ /* set the debug information address */
+ NewInfo = (MEMORY_INFO) NewMemory;
+
+ /* skip the left debug mark */
+ NewMemory += memory_OFFSET;
+#endif
+
+ /* update the pointer to the next usable block */
+ Resource->next = NewMemory + Resource->total_size;
+ }
+ }
+ }
+
+#ifdef CHECK
+ /* Set blockīs debug information */
+ memory_SetInfo(NewInfo, File, Line, NULL, 0);
+ memory_SetBlockStatusAndSize(NewMemory,
+ memory_MAGICMALLOC, Bytes);
+
+ /* delete all blockīs usable bytes with a shredder value */
+ memset(NewMemory, memory__FREESHREDDER,
+ memory_LookupRealBlockSize(Bytes));
+#endif
+
+ return NewMemory;
+}
+
+#endif
+
+
+
+#ifdef NO_MEMORY_MANAGEMENT
+
+POINTER memory_Calloc(unsigned int Elements, unsigned int Bytes)
+{
+ char *mem; /* pointer to memory block obtained from calloc */
+
+ /* Pass call through to compilerīs calloc */
+ mem = (char *)calloc(Elements, Bytes);
+
+ /* If calloc fails print an error message and exit */
+ if (mem == NULL) {
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Calloc:");
+ misc_UserErrorReport("\n Memory Error. Out of memory.\n");
+ misc_FinishUserErrorReport();
+ }
+
+ return mem;
+}
+
+#else
+
+#ifdef CHECK
+POINTER memory_CallocIntern(unsigned int Elements, unsigned int Bytes,
+ const char * File, unsigned short int Line)
+#else
+POINTER memory_Calloc(unsigned int Elements, unsigned int Bytes)
+#endif
+/********************************************************
+ INPUT : The number of requested equally huge blocks,
+ and each block's size.
+ RETURNS: A pointer to a block of (Bytes * Elements) bytes.
+ SUMMARY: Allocates a memory block of requested length
+ filled with char value '\0'.
+*********************************************************/
+{
+ char * mem; /* pointer to memory block obtained from the module */
+
+ /* Allocate memory via our memory management */
+#ifdef CHECK
+ mem = (char *)memory_MallocIntern(Elements * Bytes, File, Line);
+#else
+ mem = (char *)memory_Malloc(Elements * Bytes);
+#endif
+
+ /* If allocation was successful set all bytes to zero */
+ if (mem != NULL) {
+ memset(mem,0, Elements * Bytes);
+ }
+ /* otherwise print an error message and exit */
+ else {
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_Calloc:");
+ misc_UserErrorReport("\n Memory Error. Out of memory.\n");
+#ifdef CHECK
+ misc_UserErrorReport("\n Error occurred in memory_Calloc");
+ misc_UserErrorReport(" called from file %s at line %d.\n",
+ File, Line);
+#endif
+ misc_FinishUserErrorReport();
+ }
+
+ return mem;
+}
+#endif
+
+void memory_FreeAllMem(void)
+/**************************************************************
+ INPUT : None.
+ RETURNS: None.
+ SUMMARY: Frees all memory allocated by calls to the module.
+***************************************************************/
+{
+ int i;
+
+ /* delete all pages first by going through the memory_ARRAY.
+ This is slower than traversing the array memory_PAGES
+ directly, but is easier to implement correctly. Since
+ the only reasonable way to call memory_FreeAllMem is
+ before the program exits, a minimal performance penalty
+ should be acceptable
+ */
+
+ for (i = 1; i < memory__DYNMAXSIZE; i++) {
+ POINTER thispage, nextpage;
+ MEMORY_RESOURCE * Resource;
+
+ Resource = memory_ARRAY[i];
+
+ thispage = Resource->page;
+
+ if (*((int *)thispage) != EOF) {
+ do {
+ nextpage = *((POINTER *)thispage);
+ free(thispage);
+ thispage = nextpage;
+ } while (*((int *)thispage) != EOF);
+
+ /* and reset the resource structure */
+ Resource->page = &memory__EOF;
+ Resource->free = &memory__EOF;
+ Resource->next = &memory__EOF;
+ Resource->end_of_page = &memory__EOF;
+ }
+ }
+
+ /* now delete all big blocks left */
+
+ if (memory_BIGBLOCKS != NULL) {
+ MEMORY_BIGBLOCKHEADER thisblock, nextblock;
+
+ for (thisblock = memory_BIGBLOCKS;
+ thisblock != NULL;
+ thisblock = nextblock) {
+ nextblock = thisblock->next;
+ free(thisblock);
+ }
+
+ /* and reset the list pointer */
+ memory_BIGBLOCKS = NULL;
+ }
+}
+
+/**************************************************************/
+/* ********************************************************** */
+/* * * */
+/* * DEBUGGING INFORMATION * */
+/* * * */
+/* ********************************************************** */
+/**************************************************************/
+
+void memory_Print(void)
+/**************************************************************
+ INPUT : None.
+ RETURNS: None.
+ SUMMARY: Prints module status information to stdout:
+ the fixed size of an internal memory page, the size
+ of debug marks for a block of memory, the size of
+ demanded and freed memory in kilobytes, remaining
+ memory in bytes and the number of allocated pages of
+ memory.
+***************************************************************/
+{
+#ifndef NO_MEMORY_MANAGEMENT
+ /* Call memory_FPrint to print status information to stdout */
+ memory_FPrint(stdout);
+#endif
+}
+
+void memory_FPrint(FILE* File)
+/**************************************************************
+ INPUT : A file pointer.
+ RETURNS: None.
+ SUMMARY: Prints module status information to given File:
+ the fixed size of an internal memory page, the size
+ of debug marks for a block of memory, the size of
+ demanded and freed memory in kilobytes, remaining
+ memory in bytes and the number of allocated pages of
+ memory.
+***************************************************************/
+{
+#ifndef NO_MEMORY_MANAGEMENT
+ int Pages; /* number of allocated pages */
+ int i;
+ POINTER ActPage; /* current page in page list for a block size */
+
+ /* Calculate the total number of pages */
+ Pages = 0;
+ for (i = 1; i < memory__DYNMAXSIZE; i+=memory__SHAREDPAGES) {
+ /* increase i by memory_SHAREDPAGES due to page sharing */
+ ActPage = memory_ARRAY[i]->page;
+
+ /* Traverse the page list */
+ while (*((int *)ActPage) != EOF) {
+ Pages++;
+ ActPage = *((POINTER *)ActPage);
+ }
+ }
+
+ /* Print status information */
+ fputs("\n###\n", File);
+ fprintf(File,"### Pagesize: %d\n",
+ memory_PAGESIZE);
+ fprintf(File,"### Marksize: %d\n",
+ (int)memory_MARKSIZE);
+ fprintf(File,"### Memory demanded: %lu KBytes\n",
+ memory_NEWBYTES/memory__KILOBYTE);
+ fprintf(File,"### Memory freed: %lu KBytes\n",
+ memory_FREEDBYTES/memory__KILOBYTE);
+ fprintf(File,"### Memory remaining: %lu Bytes\n",
+ memory_NEWBYTES-memory_FREEDBYTES);
+ fprintf(File,"### Pages allocated: %d Pages\n",
+ Pages);
+ fputs("###\n", File);
+#endif
+}
+
+void memory_PrintAllocatedBlocks(unsigned int Size)
+/**************************************************************
+ INPUT : Block size.
+ RETURNS: None.
+ SUMMARY: Prints addresses of allocated memory blocks with
+ given Size to stdout, if Size is less than
+ memory_DYNMAXSIZE.
+***************************************************************/
+{
+#ifndef NO_MEMORY_MANAGEMENT
+ MEMORY_RESOURCE *Resource; /* current resource */
+
+ POINTER ActPage; /* current page */
+ POINTER ActNext; /* next usable block on current page */
+ POINTER ActEndOfPage; /* end of current page */
+
+ unsigned int BlockSize; /* current block size */
+
+#ifdef CHECK
+ MEMORY_INFO Info; /* current blockīs debug information */
+#endif
+
+ /* Allocated blocks are administered
+ in two ways depending on their
+ size. If the size is less than
+ memory__DYNMAXSIZE the block is
+ allocated from the appropriate
+ page. Otherwise the block is
+ allocated directly via a call
+ to malloc or calloc.
+
+ Thus we have two functions to
+ print the allocated blocks:
+ memory_PrintAllocatedBlocks and
+ memory_PrintAlocatedBigBlocks.
+ */
+
+
+ /* Check if memory_PrintAllocatedBlocks has been called for
+ a legal block size
+ */
+
+ if (Size >= memory__DYNMAXSIZE) {
+ /* if thatīs not the case print an error message and exit */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_PrintAllocatedBlocks:");
+ misc_UserErrorReport("\n Parameter size is too big: %d.",
+ Size);
+ misc_UserErrorReport("\n Maximal allowed value is: %d.\n",
+ memory__DYNMAXSIZE);
+ misc_FinishUserErrorReport();
+ }
+ else {
+ /* otherwise size is legal */
+
+ /* initialize the variables */
+ Resource = memory_ARRAY[Size];
+ ActPage = Resource->page;
+ ActNext = Resource->next;
+ ActEndOfPage = Resource->end_of_page;
+ BlockSize = Resource->total_size;
+
+ /* Test if there were any requests made for blocks of that size */
+ if (*((int *)ActPage) == EOF) {
+ /* Check if pointers are consistent */
+ if (*((int *)ActNext) == EOF) {
+ /* If that is true, print that information to stdout */
+ puts(" No request so far");
+ }
+ else {
+ /* Otherwise print an error message and abort */
+ misc_StartErrorReport();
+ misc_ErrorReport("\n In memory_PrintAllocatedBlocks:");
+ misc_ErrorReport("\n Memory Error. No Page entry but Next entry.\n");
+ misc_FinishErrorReport();
+ }
+ }
+ else {
+ /* We have received some requests for blocks of that size */
+#ifdef CHECK
+
+ POINTER ActData; /* current block */
+
+
+ /* Traverse through the page list for given block size */
+ while (*((int *)ActPage) != EOF) {
+
+ /* Initialize the variables */
+ ActData = (char *)ActPage + sizeof(POINTER) + memory_OFFSET;
+ ActEndOfPage = (char *)ActPage + Resource->offset;
+
+ /* Visit blocks on current page until the end of
+ page is reached, or an allocated block is found
+ */
+ while (ActData != ActNext
+ && ActData != ActEndOfPage
+ && memory_GetBlockStatus(ActData) != memory_MAGICMALLOC) {
+ ActData = (char *)ActData + BlockSize;
+ }
+
+ /* Check if there were any allocated blocks from current page */
+ if (ActData == ActNext || ActData == ActEndOfPage) {
+ /* if thatīs not the case print the information to stdout */
+ printf("\n\n No memory allocated from page at address %p\n", ActPage);
+ }
+ else {
+ /* otherwise print address and origin of (de)allocation of
+ all allocated blocks on current page, starting
+ with the block just found
+ */
+ fputs("\n\n Allocated but not freed: ", stdout);
+ do {
+ Info = (MEMORY_INFO) ((char *) ActData - memory_OFFSET);
+ if (memory_GetBlockStatus(ActData) == memory_MAGICMALLOC
+ && memory_GetBlockSize(ActData) == Size) {
+ printf("\n\t%p allocated in file %s at line %d ",
+ ActData, Info->mallocInFile, Info->mallocAtLine);
+ }
+ ActData = (char *)ActData + BlockSize;
+ } while (ActData != ActNext && ActData != ActEndOfPage);
+ }
+
+ /* go to the next page in the page list for given block size */
+ ActPage = *((POINTER *)ActPage);
+ }
+#endif
+ }
+ }
+#endif
+}
+
+void memory_PrintFreedBlocks(unsigned int Size)
+/**************************************************************
+ INPUT : Block size.
+ RETURNS: None.
+ SUMMARY: Prints addresses of freed memory blocks with given
+ Size to stdout, if Size is less than
+ memory_DYNMAXSIZE.
+***************************************************************/
+{
+#ifndef NO_MEMORY_MANAGEMENT
+ POINTER ActFree; /* current block */
+
+#ifdef CHECK
+ MEMORY_INFO Info; /* current blockīs debug information */
+#endif
+
+ /* since we donīt recycle blocks whose size is
+ greater or equal to memory__DYNMAXSIZE,
+ memory_PrintFreedBlocks is meaningless
+ for such block sizes.
+ */
+
+ /* test if given block size is legal */
+ if (Size >= memory__DYNMAXSIZE) {
+ /* if thatīs not the case print an error message and exit */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_PrintFreedBlocks.");
+ misc_UserErrorReport("\n Parameter Size is too big: %d.",
+ Size);
+ misc_UserErrorReport("\n Maximal allowed value is: %d.\n",
+ memory__DYNMAXSIZE);
+ misc_FinishUserErrorReport();
+ }
+ else {
+ /* otherwise size is legal */
+
+ /* start at the first element of the free block list
+ for the given block size
+ */
+ ActFree = memory_ARRAY[Size]->free;
+
+ /* test if the free block list is empty */
+ if (*((int *)ActFree) == EOF) {
+ /* if thatīs true, print that information to stdout */
+ puts("\n\n No freed memory");
+ }
+ else {
+ /* otherwise traverse the list of freed blocks */
+
+ fputs("\n\n Free: ", stdout);
+ while (*((int *)ActFree) != EOF) {
+#ifdef CHECK
+ /* in debug mode print current blockīs address
+ and origin of (de)allocation
+ */
+
+ /* check if blockīs size is correct */
+ if ( memory_GetBlockSize(ActFree) == Size) {
+ /* if thatīs true than print blockīs information */
+ Info = (MEMORY_INFO) ((char *) ActFree - memory_OFFSET);
+ printf("\n\t%p\tallocated in file %s at line %d",
+ ActFree, Info->mallocInFile, Info->mallocAtLine);
+ printf("\n\t\tfreed in file %s at line %d",
+ Info->freeInFile, Info->freeAtLine);
+ }
+ else {
+ /* otherwise if we are sharing pages among different
+ block sizes, the block is uncorrupted, despite not
+ matching assumed and real size. But if we are
+ not sharing pages then the block is probably corrupted,
+ so print an error message and exit
+ */
+
+ /* test if we are not in page sharing mode */
+ if (memory__SHAREDPAGES == 1) {
+ /* if thatīs true print an error message and exit */
+ misc_StartUserErrorReport();
+ misc_UserErrorReport("\n In memory_PrintFreedBlocks:");
+ misc_UserErrorReport("\n Memory Error. Memory block size mismatch.");
+ misc_UserErrorReport("\n Expected %d found %d for memory block at %p.\n",
+ Size, memory_GetBlockSize(ActFree), ActFree);
+ misc_UserErrorReport("\n Probably the memory block was corrupted.\n");
+ misc_FinishUserErrorReport();
+ }
+ }
+
+#endif
+
+ /* go to the next free block in list */
+ ActFree = *((POINTER *)ActFree);
+ }
+ }
+ }
+#endif
+}
+
+
+void memory_PrintAllocatedBigBlocks(void)
+/**************************************************************
+ INPUT : None.
+ RETURNS: None.
+ SUMMARY: Prints addresses of all allocated memory blocks,
+ that are greater than memory_DYNMAXSIZE to stdout.
+***************************************************************/
+{
+#ifndef NO_MEMORY_MANAGEMENT
+#ifdef CHECK
+ MEMORY_BIGBLOCKHEADER Ptr; /* current big block in list */
+ MEMORY_INFO Info; /* blockīs debug information */
+ char * BlockStart; /* blockīs start address */
+
+ /* start with the first block in the big block list */
+ Ptr = memory_BIGBLOCKS;
+
+ /* check whether big block list isnīt empty */
+ if (Ptr != NULL) {
+ /* if thatīs the case traverse through the list
+ and print each blockīs address, size and
+ origin of (de)allocation information
+ */
+ do {
+ BlockStart = (char *)Ptr + memory_OFFSET
+ + sizeof(MEMORY_BIGBLOCKHEADERNODE);
+
+ Info = (MEMORY_INFO) (BlockStart - memory_OFFSET);
+ printf("\n\t%p %d bytes allocated in file %s at line %d ",
+ (void*)BlockStart, memory_GetBlockSize(BlockStart),
+ Info->mallocInFile, Info->mallocAtLine);
+ Ptr = Ptr->next;
+ } while (Ptr != NULL);
+ puts("");
+ }
+ else {
+ /* otherwise there are no big blocks allocated */
+ puts(" No request so far");
+ }
+#endif
+#endif
+}
+
+void memory_PrintDetailed(void)
+/**************************************************************
+ INPUT : None.
+ RETURNS: None.
+ SUMMARY: Prints addresses of all pages, and allocated and freed
+ blocks on them.
+***************************************************************/
+{
+#ifndef NO_MEMORY_MANAGEMENT
+ MEMORY_RESOURCE *Resource; /* current resource */
+
+ POINTER ActPage; /* current page */
+ POINTER ActData; /* current block */
+ POINTER ActEndOfPage; /* end of current page */
+ unsigned int BlockSize; /* total size of a block of current size */
+ unsigned int PageOffset; /* current pageīs offset */
+
+ unsigned int i;
+
+
+ /* print end-of-memory pointerīs address */
+ printf("\n\nEOF Pointer: %p\n", (void*)&memory__EOF);
+
+ /* for all administrated block sizes print detailed information */
+ for (i=1; i<memory__DYNMAXSIZE; i++) {
+ /* initialize variables for requested block size i */
+ Resource = memory_ARRAY[i];
+ ActPage = Resource->page;
+ ActData = Resource->next;
+ ActEndOfPage = Resource->end_of_page;
+ PageOffset = Resource->offset;
+ BlockSize = Resource->total_size;
+
+ /* print requested block size, aligned block size
+ and block size including debug marks
+ */
+ printf("\n\n Entry: %d aligned size: %d total size: %d\n",
+ i , Resource->aligned_size, BlockSize);
+
+ /* Check if there were any requests for blocks of size i */
+ if (*((int *)ActPage) == EOF) {
+ /* if thatīs not the case check if memory management is consistent */
+ if (*((int *)ActData) == EOF) {
+ /* if thatīs true, print that no requests occurred to stdout */
+ puts(" No request so far");
+ }
+ else {
+ /* our memory management is no longer consistent,
+ so print an error message and abort. We hope that
+ the core dump will help us to find the bug
+ */
+ misc_StartErrorReport();
+ misc_ErrorReport("\n In memory_PrintDetailed:");
+ misc_ErrorReport("\n Memory Error. No Page entry but Next entry.\n");
+ misc_FinishErrorReport();
+ }
+ }
+ else {
+ /* we have received requests for blocks of size i */
+
+ /* traverse the list of pages for size i */
+ while (*((int *)ActPage) != EOF) {
+ /* print information about current page */
+ printf("\n\n Page: %p Next Page: %p\n",
+ ActPage, *((POINTER *)ActPage));
+
+ /* initialize variables for current page */
+ ActData = ((char *)ActPage + sizeof(POINTER) + memory_OFFSET);
+ ActEndOfPage = (char *)ActPage + PageOffset;
+
+ /* print addresses of all blocks on current page */
+ fputs(" Data: ", stdout);
+ while (ActData != ActEndOfPage) {
+ int column;
+
+ fputs("\n\t\t", stdout);
+ for (column = 0; column < 6; column++) {
+ printf("%p ", ActData);
+ ActData = (char *)ActData + BlockSize;
+ if (ActData == ActEndOfPage) {
+ break;
+ }
+ }
+ }
+
+ /* go to next page in list */
+ ActPage = *((POINTER *)ActPage);
+ }
+
+ /* print allocated and freed blocks of size i */
+ memory_PrintAllocatedBlocks(i);
+ memory_PrintFreedBlocks(i);
+ }
+ }
+
+#ifdef CHECK
+ /* print allocated blocks of size >= memory_DYNMAXSIZE */
+ printf("\n\n Allocated blocks of size >= %d\n",
+ memory__DYNMAXSIZE);
+ memory_PrintAllocatedBigBlocks();
+#endif
+#endif
+}
+
+
+void memory_PrintLeaks(void)
+/**************************************************************
+ INPUT : None.
+ RETURNS: None.
+ SUMMARY: Prints addresses of all allocated blocks. Should be
+ used at the end of a program before the call to
+ memory_FreeAllMem.
+***************************************************************/
+{
+#ifndef NO_MEMORY_MANAGEMENT
+ POINTER ActPage; /* current page */
+ POINTER ActNext; /* next fresh block on current page */
+ POINTER ActEndOfPage; /* end of current page */
+ MEMORY_RESOURCE *Resource; /* current resource */
+ unsigned int Size; /* current size */
+ unsigned int BlockSize; /* total block size */
+
+ /* Check if some memory is still allocated */
+ if (memory_UsedBytes() != 0L) {
+
+ /* If thatīs true, print all allocated blocks */
+
+ /* Start with blocks administered by our memory management */
+ for (Size = 1; Size < memory__DYNMAXSIZE; Size++) {
+ /* Initialize variables for current block size */
+ Resource = memory_ARRAY[Size];
+ ActPage = Resource->page;
+ ActNext = Resource->next;
+ ActEndOfPage = Resource->end_of_page;
+ BlockSize = Resource->total_size;
+
+ /* Check if there were any requests for
+ memory blocks of that size */
+ if (*((int *)ActPage) != EOF) {
+
+ /* if thatīs true, browse through all blocks on all pages
+ to find a block that is still allocated
+ */
+#ifdef CHECK
+
+ POINTER ActData;
+ BOOL LeakFound;
+
+ LeakFound = FALSE;
+
+ while (*((int *)ActPage) != EOF) {
+
+ /* search through all pages for a block that is still allocated */
+
+ ActData = (char *)ActPage + sizeof(POINTER) + memory_OFFSET;
+ ActEndOfPage = (char *)ActPage + Resource->offset;
+
+ while (ActData != ActNext && ActData != ActEndOfPage) {
+ if (memory_GetBlockStatus(ActData) == memory_MAGICMALLOC) {
+ LeakFound = TRUE;
+ break;
+ }
+ ActData = (char *)ActData + BlockSize;
+ }
+
+ if (LeakFound) {
+
+ /* if we have found one, than call memory_PrintAllocatedBlocks
+ to print its address */
+
+ printf("\n\n Leaked blocks of size %d:", Size);
+
+ memory_PrintAllocatedBlocks(Size);
+ putchar('\n');
+ /* since memory_PrintAllocatedblocks prints
+ *all* allocated blocks of specific size, we can
+ break out of the while loop
+ */
+ break;
+ }
+ else {
+ /* go to next page */
+ ActPage = *((POINTER *)ActPage);
+ }
+ }
+
+#endif
+
+ }
+ }
+
+#ifdef CHECK
+ /* Print allocated blocks of size >= memory__DYNMAXSIZE */
+ if (memory_BIGBLOCKS != NULL) {
+ printf("\n\n Leaked blocks of size >= %d\n",
+ memory__DYNMAXSIZE);
+ memory_PrintAllocatedBigBlocks();
+ putchar('\n');
+ }
+#endif
+
+ }
+#endif
+}