source: trunk/third/gmp/tal-debug.c @ 18191

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