⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sflmem.c

📁 短小精悍的C语言标准函数库。提供450个以上的可移植的算法和工具代码。
💻 C
📖 第 1 页 / 共 3 页
字号:


/*  ---------------------------------------------------------------------[<]-
    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 + -