📄 sflmem.c
字号:
{
LIST
*ptr;
# if (defined (MEM_TRACE))
trace ("%s (%ld): commit transaction",
filename? filename: "-", (long) lineno);
# endif
ptr = &trn-> memhdr;
if (!list_empty (ptr)) /* Are there any blocks to commit? */
{
list_relink_before (ptr, /* Relink list into main list */
&mem_list. memhdr);
list_unlink (ptr);
}
mem_del_trans (trn);
}
/* --------------------------------------------------------------------------
* mem_del_trans - internal
*
* Deletes a transaction block.
*/
static void
mem_del_trans(
MEMTRN *trn
)
{
if (trn == NULL) /* Do nothing if address is null */
return;
ASSERT (list_empty (&trn-> memhdr));
list_unlink (trn); /* Remove transaction from list */
free (trn);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_rollback_
Synopsis: Rolls back allocations for a particular transaction. This
frees up all blocks allocated by calls to mem_alloc, mem_realloc and
mem_strdup since the last call to mem_commit. Note that for blocks
allocated with mem_realloc, this is not really a rollback but a free.
The mem_rollback() function must be used with some care... if you
forget to do a mem_commit(), a later mem_rollback() will do damage
to your memory space. The general rule is to start your processing
with mem_commit(), then do work, and call mem_rollback() when there
is an error. Finally, call mem_commit() at the end.
---------------------------------------------------------------------[>]-*/
void
mem_rollback_ (
MEMTRN *trn,
const char *filename, /* Name of source file making call */
size_t lineno /* Line number in calling source */
)
{
# if (defined (MEM_TRACE))
trace ("%s (%ld): rollback transaction",
filename? filename: "-", (long) lineno);
# endif
mem_free_list ((MEMHDR *) &trn-> memhdr);
mem_del_trans (trn);
}
/* ---------------------------------------------------------------------------
* mem_free_list -- internal
*
*/
static void
mem_free_list (
MEMHDR *list /* List of memory allocations */
)
{
MEMHDR
*ptr;
while (!list_empty (list))
{
ptr = list-> next;
ptr-> tag = MEMUNTAG;
mem_total -= ptr-> size;
mem_free_count += 1;
list_unlink (ptr); /* Remove block from list */
free (ptr);
}
}
/* ---------------------------------------------------------------------[<]-
Function: mem_size_
Synopsis: Returns the size in bytes of a memory block.
---------------------------------------------------------------------[>]-*/
size_t
mem_size_ (
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 0;
/* Check for valid block */
ptr = CLIENT_2_HDR (client_ptr);
if (ptr-> tag != MEMTAG)
mem_tag_err (ptr, filename, lineno);
return (ptr-> size);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_used
Synopsis: Returns the number of bytes currently allocated using the
memory management system. The value returned is simply the sum of the
size requests to allocation routines. It does not reflect any overhead
required by the memory management system.
---------------------------------------------------------------------[>]-*/
long
mem_used (void)
{
return (mem_total);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_allocs
Synopsis: Returns the number of blocks allocated in total. Use this
to get an idea of the activity of the memory management system. When
program ends cleanly, mem_allocs () should be equal to mem_frees().
---------------------------------------------------------------------[>]-*/
long
mem_allocs (void)
{
return (mem_alloc_count);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_frees
Synopsis: Returns the number of blocks freed in total. Use this
to get an idea of the activity of the memory management system. When
program ends cleanly, mem_allocs () should be equal to mem_frees().
---------------------------------------------------------------------[>]-*/
long
mem_frees (void)
{
return (mem_free_count);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_display
Synopsis: Displays the contents of the memory allocation list.
---------------------------------------------------------------------[>]-*/
void
mem_display (
FILE *fp /* File to dump display to */
)
{
MEMTRN
*trn;
fprintf (fp, "Index Size File(Line) - total size %lu\n", mem_total);
mem_display_list ((MEMHDR *) &mem_list.memhdr, fp);
trn = tr_list.next;
while (trn != (MEMTRN *) &tr_list)
{
fprintf (fp, "* Transaction %s (%ld)",
trn-> file? trn-> file: "<Unknown>", (long) trn-> line);
fprintf (fp, "\n");
mem_display_list ((MEMHDR *) &trn-> memhdr, fp);
trn = trn-> next;
}
fflush (fp);
}
/* ---------------------------------------------------------------------------
* mem_display_list -- internal
*
* Displays memory allocations attached to a particular list
*/
static void
mem_display_list (
MEMHDR *lst, /* List of memory allocations */
FILE *fp /* File to dump display to */
)
{
MEMHDR
*ptr;
int
index;
index = 0;
ptr = lst-> next;
while (ptr != lst)
{
fprintf (fp, "%-5d %6ld", index++, (long) ptr-> size);
fprintf (fp, " %s (%ld)",
ptr-> file? ptr-> file: "<Unknown>", (long) ptr-> line);
if (ptr-> tag != MEMTAG)
fprintf (fp, " INVALID");
fprintf (fp, " [%p]\n", HDR_2_CLIENT (ptr));
ptr = ptr-> next;
}
}
/* ---------------------------------------------------------------------[<]-
Function: mem_scavenger
Synopsis: Registers a memory scavenger function. A memory scavenger
function is an application function that is invoked by mem_alloc_() when
memory is exhausted, so that unused application objects can be released.
This allows you to allocate large amounts of memory -- for instance for
caches -- and then release them when memory runs short. When you
register a scavenger function you may provide a void * argument; this is
passed back to the scavenger if it is ever invoked. The scavenger
function returns TRUE if it could release some memory, otherwise it
returns FALSE. Note that there is no way to unregister such a function.
Furthermore, a scavenger function should not itself allocate any new
memory, unless it can definitely free excess memory first. Scavenger
functions are called in an unspecified order. Returns 0 if the scavenger
function could be registered, -1 if not. There is no limit to the number
of scavenger functions you can register, except available memory. The
same scavenger function can be registered several times.
---------------------------------------------------------------------[>]-*/
int
mem_scavenger (
scavenger scav_fct, /* File to dump display to */
void * scav_arg
)
{
SCAVFCT
*scavfct; /* Allocated registry function */
/* Allocate an SCAVFCT block and attach it to the scavfcts list */
list_create (scavfct, sizeof (SCAVFCT));
if (scavfct == NULL)
return (-1);
list_relink_before (scavfct, &scavfcts);
scavfct-> scav_fct = scav_fct;
scavfct-> scav_arg = scav_arg;
return (0);
}
/* ---------------------------------------------------------------------[<]-
Function: mem_freeall
Synopsis: Frees all allocated memory. This function is rather brutal and
can do strange things to an application. It can be useful when you are
trying to recover control in a crashed application, and need to free all
allocated memory before restarting it.
---------------------------------------------------------------------[>]-*/
void
mem_freeall (void)
{
MEMTRN
*trn;
mem_free_list ((MEMHDR *) &mem_list.memhdr);
while (!list_empty (&tr_list))
{
trn = tr_list.next;
mem_free_list ((MEMHDR *) &trn-> memhdr);
mem_del_trans (trn);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -