github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tal-debug.c (about)

     1  /* TMP_ALLOC routines for debugging.
     2  
     3  Copyright 2000, 2001, 2004 Free Software Foundation, Inc.
     4  
     5  This file is part of the GNU MP Library.
     6  
     7  The GNU MP Library is free software; you can redistribute it and/or modify
     8  it under the terms of either:
     9  
    10    * the GNU Lesser General Public License as published by the Free
    11      Software Foundation; either version 3 of the License, or (at your
    12      option) any later version.
    13  
    14  or
    15  
    16    * the GNU General Public License as published by the Free Software
    17      Foundation; either version 2 of the License, or (at your option) any
    18      later version.
    19  
    20  or both in parallel, as here.
    21  
    22  The GNU MP Library is distributed in the hope that it will be useful, but
    23  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    24  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    25  for more details.
    26  
    27  You should have received copies of the GNU General Public License and the
    28  GNU Lesser General Public License along with the GNU MP Library.  If not,
    29  see https://www.gnu.org/licenses/.  */
    30  
    31  #include <stdio.h>
    32  #include <stdlib.h>
    33  #include <string.h>
    34  #include "gmp.h"
    35  #include "gmp-impl.h"
    36  
    37  
    38  /* This method aims to help a malloc debugger find problems.  A linked list
    39     of allocated block is kept for TMP_FREE to release.  This is reentrant
    40     and thread safe.
    41  
    42     Each TMP_ALLOC is a separate malloced block, so redzones or sentinels
    43     applied by a malloc debugger either above or below can guard against
    44     accesses outside the allocated area.
    45  
    46     A marker is a "struct tmp_debug_t *" so that TMP_DECL can initialize it
    47     to NULL and we can detect TMP_ALLOC without TMP_MARK.
    48  
    49     It will work to realloc an MPZ_TMP_INIT variable, but when TMP_FREE comes
    50     to release the memory it will have the old size, thereby triggering an
    51     error from tests/memory.c.
    52  
    53     Possibilities:
    54  
    55     It'd be possible to keep a global list of active "struct tmp_debug_t"
    56     records, so at the end of a program any TMP leaks could be printed.  But
    57     if only a couple of routines are under test at any one time then the
    58     likely culprit should be easy enough to spot.  */
    59  
    60  
    61  void
    62  __gmp_tmp_debug_mark (const char *file, int line,
    63                        struct tmp_debug_t **markp, struct tmp_debug_t *mark,
    64                        const char *decl_name, const char *mark_name)
    65  {
    66    if (strcmp (mark_name, decl_name) != 0)
    67      {
    68        __gmp_assert_header (file, line);
    69        fprintf (stderr, "GNU MP: TMP_MARK(%s) but TMP_DECL(%s) is in scope\n",
    70                 mark_name, decl_name);
    71        abort ();
    72      }
    73  
    74    if (*markp != NULL)
    75      {
    76        __gmp_assert_header (file, line);
    77        fprintf (stderr, "GNU MP: Repeat of TMP_MARK(%s)\n", mark_name);
    78        if (mark->file != NULL && mark->file[0] != '\0' && mark->line != -1)
    79          {
    80            __gmp_assert_header (mark->file, mark->line);
    81            fprintf (stderr, "previous was here\n");
    82          }
    83        abort ();
    84      }
    85  
    86    *markp = mark;
    87    mark->file = file;
    88    mark->line = line;
    89    mark->list = NULL;
    90  }
    91  
    92  void *
    93  __gmp_tmp_debug_alloc (const char *file, int line, int dummy,
    94                         struct tmp_debug_t **markp,
    95                         const char *decl_name, size_t size)
    96  {
    97    struct tmp_debug_t        *mark = *markp;
    98    struct tmp_debug_entry_t  *p;
    99  
   100    ASSERT_ALWAYS (size >= 1);
   101  
   102    if (mark == NULL)
   103      {
   104        __gmp_assert_header (file, line);
   105        fprintf (stderr, "GNU MP: TMP_ALLOC without TMP_MARK(%s)\n", decl_name);
   106        abort ();
   107      }
   108  
   109    p = __GMP_ALLOCATE_FUNC_TYPE (1, struct tmp_debug_entry_t);
   110    p->size = size;
   111    p->block = (*__gmp_allocate_func) (size);
   112    p->next = mark->list;
   113    mark->list = p;
   114    return p->block;
   115  }
   116  
   117  void
   118  __gmp_tmp_debug_free (const char *file, int line, int dummy,
   119                        struct tmp_debug_t **markp,
   120                        const char *decl_name, const char *free_name)
   121  {
   122    struct tmp_debug_t        *mark = *markp;
   123    struct tmp_debug_entry_t  *p, *next;
   124  
   125    if (mark == NULL)
   126      {
   127        __gmp_assert_header (file, line);
   128        fprintf (stderr, "GNU MP: TMP_FREE(%s) without TMP_MARK(%s)\n",
   129                 free_name, decl_name);
   130        abort ();
   131      }
   132  
   133    if (strcmp (free_name, decl_name) != 0)
   134      {
   135        __gmp_assert_header (file, line);
   136        fprintf (stderr, "GNU MP: TMP_FREE(%s) when TMP_DECL(%s) is in scope\n",
   137                 free_name, decl_name);
   138        abort ();
   139      }
   140  
   141    p = mark->list;
   142    while (p != NULL)
   143      {
   144        next = p->next;
   145        (*__gmp_free_func) (p->block, p->size);
   146        __GMP_FREE_FUNC_TYPE (p, 1, struct tmp_debug_entry_t);
   147        p = next;
   148      }
   149  
   150    *markp = NULL;
   151  }