xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/memory.c (revision 8450a7c42673d65e3b1f6560d3b6ecd317a6cbe8)
1 /* Memory allocation used during tests.
2 
3 Copyright 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramel projects, INRIA.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 
23 /* Note: this file comes from GMP's tests/memory.c */
24 
25 #include <stdio.h>
26 #include <stdlib.h>  /* for abort */
27 #include <limits.h>
28 
29 #include "mpfr-test.h"
30 
31 /* Each block allocated is a separate malloc, for the benefit of a redzoning
32    malloc debugger during development or when bug hunting.
33 
34    Sizes passed when reallocating or freeing are checked (the default
35    routines don't care about these).
36 
37    Memory leaks are checked by requiring that all blocks have been freed
38    when tests_memory_end() is called.  Test programs must be sure to have
39    "clear"s for all temporary variables used.  */
40 
41 struct header {
42   void           *ptr;
43   size_t         size;
44   struct header  *next;
45 };
46 
47 static struct header  *tests_memory_list;
48 
49 /* Return a pointer to a pointer to the found block (so it can be updated
50    when unlinking). */
51 static struct header **
52 tests_memory_find (void *ptr)
53 {
54   struct header  **hp;
55 
56   for (hp = &tests_memory_list; *hp != NULL; hp = &((*hp)->next))
57     if ((*hp)->ptr == ptr)
58       return hp;
59 
60   return NULL;
61 }
62 
63 /*
64 static int
65 tests_memory_valid (void *ptr)
66 {
67   return (tests_memory_find (ptr) != NULL);
68 }
69 */
70 
71 static void *
72 tests_allocate (size_t size)
73 {
74   struct header  *h;
75 
76   if (size == 0)
77     {
78       printf ("tests_allocate(): attempt to allocate 0 bytes\n");
79       abort ();
80     }
81 
82   h = (struct header *) __gmp_default_allocate (sizeof (*h));
83   h->next = tests_memory_list;
84   tests_memory_list = h;
85 
86   h->size = size;
87   h->ptr = __gmp_default_allocate (size);
88   return h->ptr;
89 }
90 
91 static void *
92 tests_reallocate (void *ptr, size_t old_size, size_t new_size)
93 {
94   struct header  **hp, *h;
95 
96   if (new_size == 0)
97     {
98       printf ("tests_reallocate(): attempt to reallocate 0x%lX to 0 bytes\n",
99               (unsigned long) ptr);
100       abort ();
101     }
102 
103   hp = tests_memory_find (ptr);
104   if (hp == NULL)
105     {
106       printf ("tests_reallocate(): attempt to reallocate bad pointer 0x%lX\n",
107               (unsigned long) ptr);
108       abort ();
109     }
110   h = *hp;
111 
112   if (h->size != old_size)
113     {
114       /* Note: we should use the standard %zu to print sizes, but
115          this is not supported by old C implementations. */
116       printf ("tests_reallocate(): bad old size %lu, should be %lu\n",
117               (unsigned long) old_size, (unsigned long) h->size);
118       abort ();
119     }
120 
121   h->size = new_size;
122   h->ptr = __gmp_default_reallocate (ptr, old_size, new_size);
123   return h->ptr;
124 }
125 
126 static struct header **
127 tests_free_find (void *ptr)
128 {
129   struct header  **hp = tests_memory_find (ptr);
130   if (hp == NULL)
131     {
132       printf ("tests_free(): attempt to free bad pointer 0x%lX\n",
133               (unsigned long) ptr);
134       abort ();
135     }
136   return hp;
137 }
138 
139 static void
140 tests_free_nosize (void *ptr)
141 {
142   struct header  **hp = tests_free_find (ptr);
143   struct header  *h = *hp;
144 
145   *hp = h->next;  /* unlink */
146 
147   __gmp_default_free (ptr, h->size);
148   __gmp_default_free (h, sizeof (*h));
149 }
150 
151 static void
152 tests_free (void *ptr, size_t size)
153 {
154   struct header  **hp = tests_free_find (ptr);
155   struct header  *h = *hp;
156 
157   if (h->size != size)
158     {
159       /* Note: we should use the standard %zu to print sizes, but
160          this is not supported by old C implementations. */
161       printf ("tests_free(): bad size %lu, should be %lu\n",
162               (unsigned long) size, (unsigned long) h->size);
163       abort ();
164     }
165 
166   tests_free_nosize (ptr);
167 }
168 
169 void
170 tests_memory_start (void)
171 {
172   tests_memory_list = NULL;
173   mp_set_memory_functions (tests_allocate, tests_reallocate, tests_free);
174 }
175 
176 void
177 tests_memory_end (void)
178 {
179   if (tests_memory_list != NULL)
180     {
181       struct header  *h;
182       unsigned  count;
183 
184       printf ("tests_memory_end(): not all memory freed\n");
185 
186       count = 0;
187       for (h = tests_memory_list; h != NULL; h = h->next)
188         count++;
189 
190       printf ("    %u blocks remaining\n", count);
191       abort ();
192     }
193 }
194