blob: 07efdc8e2e3bce898d2d51769f66224d351f88ab [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2008 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
/*****************************************************************************
* Utility Library
*
* DESCRIPTION
* Memory allocation wrapper functions. These wrapper functions provide
* the following benefits:
*
* - Report failures using utlError so you don't need to every time you
* call malloc/realloc/calloc.
*
* - Allow reported errors to include information about from where in
* your source code the calls to malloc/realloc/calloc/free were made.
* This is useful when trying to track down memory leaks.
*
* - Arranges for free'ed pointers to be assigned the value "NULL", to
* better detect when an application attempts to access free'ed memory.
*
* - Makes it easier to later add test code to check for write-boundary
* violations, memory leaks, and so forth (Future feature).
*
* EXAMPLE USAGE
*
* --- malloc/realloc ---
* {
* char *c_p;
*
* if ((c_p = utlMalloc(100 * sizeof(char))) == NULL)
* <handle error here>
*
* <use `c_p' here>
*
* {
* char *new_c_p;
*
* if ((new_c_p = utlRealloc(c_p, 200 * sizeof(char))) == NULL)
* <handle error here>
*
* c_p = new_c_p;
* }
*
* <use resize'ed `c_p' here>
*
* utlFree(c_p);
* }
*
* --- malloc/realloc ---
* {
* char *c_p;
*
* if ((c_p = utlCalloc(100, sizeof(char))) == NULL)
* <handle error here>
*
* <use `c_p' here>
*
* utlFree(c_p);
* }
*
* Note: Use "utlFreeConst()" if you're trying to free a pointer that has
* been declared as a "const". "utlFreeConst()" does not attempt
* to NULL the just-free'ed pointer.
*
* Note: According to ANSI-C, if realloc() returns NULL, the block of
* memory originally passed to realloc() remains allocated and
* must eventually be free'ed to avoid a memory leak. Loosing
* track of this original block is a very common programming
* error.
*
*****************************************************************************/
#include <stdio.h>
#include "utlTypes.h"
#include "utlError.h"
#include "utlMalloc.h"
#include "utlTrace.h"
/*--- Configuration ---------------------------------------------------------*/
/*--- for tracing heap allocs and frees ---*/
#define utlTRACE_HEAP "heap"
/*---------------------------------------------------------------------------*
* FUNCTION
* utlDoFree(utlHERE_DECLARATION, buf_p)
* INPUT
* utlHERE_DECLARATION == source of free request
* buf_p == the buffer to free
* OUTPUT
* none
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Free's one block of allocated memory.
*---------------------------------------------------------------------------*/
void utlDoFree(utlHERE_DECLARATION,
void *buf_p)
{
utlTrace(utlTRACE_HEAP,
utlPrintTrace(utlDoFree, "%s/%s/line=%d, Free 0x%x\n",
utlHERE_FILE,
utlHERE_FUNC,
utlHERE_LINE,
(unsigned int)buf_p);
);
free(buf_p);
}
/*---------------------------------------------------------------------------*
* FUNCTION
* utlDoMalloc(utlHERE_DECLARATION, siz)
* INPUT
* utlHERE_DECLARATION == source of malloc request
* siz == number of bytes to allocate
* OUTPUT
* none
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Allocates one block of memory.
*---------------------------------------------------------------------------*/
void *utlDoMalloc(utlHERE_DECLARATION,
const size_t siz)
{
void *buf_p;
if ((buf_p = malloc(siz)) == NULL)
{
utlError(utlDoMalloc, "Call to malloc(%d) failed\n", siz);
return NULL;
}
utlTrace(utlTRACE_HEAP,
utlPrintTrace(utlDoMalloc1, "%s/%s/line=%d, Malloc(%d bytes) 0x%x\n",
utlHERE_FILE,
utlHERE_FUNC,
utlHERE_LINE,
siz,
(unsigned int)buf_p);
);
return buf_p;
}
/*---------------------------------------------------------------------------*
* FUNCTION
* utlDoRealloc(utlHERE_DECLARATION, buf_p, siz)
* INPUT
* utlHERE_DECLARATION == source of realloc request
* buf_p == pointer to the allocated block to be resized, or NULL
* siz == number of bytes to allocate
* OUTPUT
* none
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Resizes an allocated block of memory.
*---------------------------------------------------------------------------*/
void *utlDoRealloc(utlHERE_DECLARATION,
void *buf_p,
const size_t siz)
{
void *new_buf_p;
if ((new_buf_p = realloc(buf_p, siz)) == NULL)
{
utlError(utlDoRealloc, "Call to realloc(0x%x, %d) failed\n", buf_p, siz);
return NULL;
}
utlTrace(utlTRACE_HEAP,
utlPrintTrace(utlDoRealloc1, "%s/%s/line=%d, Relloc(%d bytes) from 0x%x to 0x%x\n",
utlHERE_FILE,
utlHERE_FUNC,
utlHERE_LINE,
siz,
(unsigned int)buf_p,
(unsigned int)new_buf_p);
);
return new_buf_p;
}
/*---------------------------------------------------------------------------*
* FUNCTION
* utlDoCalloc(utlHERE_DECLARATION, number_of, siz)
* INPUT
* utlHERE_DECLARATION == source of calloc request
* number_of == number of blocks to allocate
* siz == number of bytes in each block
* OUTPUT
* none
* RETURNS
* utlSUCCESS for success, utlFAILED for failure
* DESCRIPTION
* Allocates and initializes multiple same-sized contigious blocks of
* memory.
*---------------------------------------------------------------------------*/
void *utlDoCalloc(utlHERE_DECLARATION,
const size_t number_of,
const size_t siz)
{
void *buf_p;
if ((buf_p = calloc(number_of, siz)) == NULL)
{
utlError(utlDoCalloc, "Call to calloc(%d, %d) failed\n", number_of, siz);
return NULL;
}
utlTrace(utlTRACE_HEAP,
utlPrintTrace(utlDoCalloc1, "%s/%s/line=%d, Calloc(%d %d-byte blocks) %p\n",
utlHERE_FILE,
utlHERE_FUNC,
utlHERE_LINE,
number_of,
siz,
buf_p);
);
return buf_p;
}
#ifdef utlTEST
/*---------------------------------------------------------------------------*
* FUNCTION
* mallocTest()
* INPUT
* none
* OUTPUT
* none
* RETURNS
* "true" for pass, "false" for failure
*---------------------------------------------------------------------------*/
bool mallocTest(void)
{
void *buf_p;
/*--- utlMalloc() -------------------------------------------------------*/
if ((buf_p = utlMalloc(10)) == NULL)
{
(void)fprintf(stderr, "memoryTest: utlMalloc() failed\n");
return false;
}
utlFree(buf_p);
if (buf_p != NULL)
{
(void)fprintf(stderr, "memoryTest: utlFree() failed\n");
return false;
}
/*--- utlRealloc() ------------------------------------------------------*/
if ((buf_p = utlMalloc(10)) == NULL)
{
(void)fprintf(stderr, "memoryTest: utlMalloc() failed\n");
return false;
}
if ((buf_p = utlRealloc(buf_p, 20)) == NULL)
{
(void)fprintf(stderr, "memoryTest: utlRealloc() failed\n");
return false;
}
utlFree(buf_p);
if (buf_p != NULL)
{
(void)fprintf(stderr, "memoryTest: utlFree() failed\n");
return false;
}
/*--- utlCalloc() -------------------------------------------------------*/
if ((buf_p = utlCalloc(10, 5)) == NULL)
{
(void)fprintf(stderr, "memoryTest: utlCalloc() failed\n");
return false;
}
utlFree(buf_p);
if (buf_p != NULL)
{
(void)fprintf(stderr, "memoryTest: utlFree() failed\n");
return false;
}
return true;
}
#endif /* utlTEST */