📄 sflmem.c
字号:
/* ---------------------------------------------------------------------[<]-
Function: mem_strfree_
Synopsis: Releases memory occupied by a string. Use the mem_strfree()
macro to call this function! Call this function to free strings
allocated using mem_strdup_(). Accepts the address of a char pointer
as argument: if the pointer is not null, the string is freed, and the
pointer is set to null. Returns the address of the modified pointer.
Examples:
char
*string1 = NULL,
*string2 = NULL;
string1 = mem_strdup ("This is a string");
mem_strfree (&string1);
mem_strfree (&string2);
---------------------------------------------------------------------[>]-*/
void
mem_strfree_ (
char **string, /* Address of string to free */
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
ASSERT (string);
if (*string)
{
mem_free_ (*string, filename, lineno);
*string = NULL;
}
}
/* ---------------------------------------------------------------------[<]-
Function: mem_free_
Synopsis: Releases memory previously allocated by mem_alloc_(),
mem_realloc_(), or mem_strdup_(). Use the mem_free() macro to call
this function! If the specified block was not correctly allocated,
dumps the memory allocation list and exits. If you specify a null
address, does nothing.
---------------------------------------------------------------------[>]-*/
void
mem_free_ (
void *client_ptr, /* Block of memory to free */
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
MEMHDR
*ptr;
if (client_ptr == NULL) /* Do nothing if address is null */
return;
/* Check for valid block */
ptr = CLIENT_2_HDR (client_ptr);
if (ptr-> tag != MEMTAG)
mem_tag_err (ptr, filename, lineno);
# if (defined (MEM_TRACE))
trace ("%s (%ld): free=%p",
filename? filename: "-", (long) lineno, ptr);
# endif
# if (defined (DEBUG))
memset (client_ptr, 0, ptr-> size);
# endif
/* Invalidate header */
ptr-> tag = MEMUNTAG;
mem_total -= ptr-> size;
mem_free_count += 1;
/* Remove block from list, inlining code from list_unlink() */
((LIST *) ((LIST *) ptr)-> prev)-> next = ((LIST *) ptr)-> next;
((LIST *) ((LIST *) ptr)-> next)-> prev = ((LIST *) ptr)-> prev;
free (ptr);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_assert_
Synopsis: Checks that all allocated memory was freed. Use the
mem_assert macro to call this function! If any memory is still left
allocated, displays the memory list on stderr and aborts. Generally
we use this function at the end of a program, after deallocating all
memory. If any memory has not been allocated, we get a nice list and
an abort. Our principle is that any memory allocation must be matched
by a free somewhere in the code.
---------------------------------------------------------------------[>]-*/
void
mem_assert_ (
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
FILE
*trace_file;
if (mem_total != 0
|| !list_empty (&tr_list))
{
fflush (stdout);
fprintf (stderr, "Clean-memory assertion failed - %s (%ld)\n",
filename? filename: "<Unknown>", (long) lineno);
fprintf (stderr, "Details are in memtrace.lst\n");
trace_file = fopen ("memtrace.lst", "w");
mem_display (trace_file);
fclose (trace_file);
abort ();
}
}
/* ---------------------------------------------------------------------[<]-
Function: mem_checkall_
Synopsis: Checks all allocated memory blocks; if any block was corrupted,
aborts with an error message, else does nothing.
---------------------------------------------------------------------[>]-*/
void
mem_checkall_ (
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
MEMTRN
*trn;
# if (defined (MEM_TRACE))
trace ("%s (%ld): check all memory",
filename? filename: "-", (long) lineno);
# endif
mem_check_list ((MEMHDR *) &mem_list.memhdr, filename, lineno);
trn = tr_list.next;
while (trn != (MEMTRN *) &tr_list)
{
mem_check_list ((MEMHDR *) &trn-> memhdr, filename, lineno);
trn = trn-> next;
}
}
/* ---------------------------------------------------------------------------
* mem_check_list -- internal
*
* Checks memory blocks in one transaction; if any block was corrupted,
* aborts with an error message, else does nothing.
*/
static void
mem_check_list (
MEMHDR *lst, /* List of memory allocations */
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
MEMHDR
*ptr;
ptr = mem_list.memhdr.next;
ptr = lst-> next;
while (ptr != lst)
{
if (ptr-> tag != MEMTAG)
{
mem_display (stderr);
mem_tag_err (ptr, filename, lineno);
}
ptr = ptr-> next;
}
}
/* ---------------------------------------------------------------------[<]-
Function: mem_check_
Synopsis: Checks that a block of memory has not been corrupted. If the
block is corrupted, aborts with an error message, else does nothing.
---------------------------------------------------------------------[>]-*/
void
mem_check_ (
const void *client_ptr, /* Block of memory to free */
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
MEMHDR
*ptr;
if (client_ptr == NULL) /* Do nothing if address is null */
return;
/* Check for valid block */
ptr = CLIENT_2_HDR (client_ptr);
if (ptr-> tag != MEMTAG)
mem_tag_err (ptr, filename, lineno);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_descr_
Synopsis: Allocates a DESCR block for a specified block of data. Use the
mem_descr macro to call this function! Returns a pointer to an allocated
DESCR block, or NULL if there was not enough memory. The DESCR block is
allocated as a single block, consisting of the DESCR block plus the data.
To free the entire block you need one call to mem_free(). If the
data_block argument is not null, its contents are copied into the newly
allocated memory.
---------------------------------------------------------------------[>]-*/
DESCR *
mem_descr_ (
MEMTRN *trn, /* Associated transaction */
const void *data_block, /* Block of memory to copy */
size_t data_size, /* Size of memory block */
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
DESCR
*descr;
descr = mem_alloc_ (trn, data_size + sizeof (DESCR), filename, lineno);
if (descr == NULL)
return (NULL);
# if (defined (MEM_TRACE))
trace ("%s (%ld): allocate descr=%p",
filename? filename: "-", (long) lineno, descr);
# endif
/* Fill-in descriptor block unless it is NULL */
descr-> size = data_size;
descr-> data = (byte *) descr + sizeof (DESCR);
if (data_block)
memcpy (descr-> data, data_block, data_size);
return (descr);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_new_trans_
Synopsis: Allocates a transaction block. Use the mem_new_trans()
macro to call this function. Use mem_commit to save or mem_rollback() to
delete the transaction. Returns a pointer to the allocated transaction
block, or NULL if there was not enough memory available. The supplied
source file name is assumed to be in a static area.
---------------------------------------------------------------------[>]-*/
MEMTRN *
mem_new_trans_(
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
MEMTRN
*trn; /* Allocated transaction block */
/* Allocate block */
trn = malloc (MEMTRN_SIZE);
if (trn == NULL)
return (NULL);
# if (defined (MEM_TRACE))
trace ("%s (%ld): new transaction",
filename? filename: "-", (long) lineno);
# endif
trn-> file = (char *) filename; /* Who allocated it */
trn-> line = lineno; /* and where */
list_reset (&trn-> memhdr); /* No memory blocks yet */
list_reset (trn); /* Only 1 item in list */
list_relink_before (trn, &tr_list); /* Add to list of transactions */
return (trn); /* and return address */
}
/* ---------------------------------------------------------------------[<]-
Function: mem_commit_
Synopsis: Commits all blocks allocated to a given transaction.
---------------------------------------------------------------------[>]-*/
void
mem_commit_ (
MEMTRN *trn,
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -