]> sjero.net Git - wget/blob - src/xmalloc.c
Fix ISDIGIT to c_isdigit.
[wget] / src / xmalloc.c
1 /* Wrappers around malloc and memory debugging support.
2    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation,
3    Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work.  */
30
31 #include "wget.h"
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <assert.h>
38
39 #include "xmalloc.h"
40 #include "hash.h"               /* for hash_pointer */
41
42 /* This file implements several wrappers around the basic allocation
43    routines.  This is done for two reasons: first, so that the callers
44    of these functions need not check for errors, which is easy to
45    forget.  If there is not enough virtual memory for running Wget,
46    something is seriously wrong, and Wget exits with an appropriate
47    error message.
48
49    The second reason why these are useful is that, if DEBUG_MALLOC is
50    defined, they also provide a handy (if crude) malloc debugging
51    interface that checks for memory leaks.  */
52
53 /* Croak the fatal memory error and bail out with non-zero exit
54    status.  */
55
56 void
57 memfatal (const char *context, long attempted_size)
58 {
59   /* Make sure we don't try to store part of the log line, and thus
60      call malloc.  */
61   log_set_save_context (false);
62
63   /* We have different log outputs in different situations:
64      1) output without bytes information
65      2) output with bytes information  */
66   if (attempted_size == UNKNOWN_ATTEMPTED_SIZE)
67     {
68       logprintf (LOG_ALWAYS,
69                  _("%s: %s: Failed to allocate enough memory; memory exhausted.\n"),
70                  exec_name, context);
71     }
72   else
73     {
74       logprintf (LOG_ALWAYS,
75                  _("%s: %s: Failed to allocate %ld bytes; memory exhausted.\n"),
76                  exec_name, context, attempted_size);
77     }
78
79   exit (1);
80 }
81
82 /* These functions end with _real because they need to be
83    distinguished from the debugging functions, and from the macros.
84    Explanation follows:
85
86    If memory debugging is not turned on, xmalloc.h defines these:
87
88      #define xmalloc checking_malloc
89      #define xmalloc0 checking_malloc0
90      #define xrealloc checking_realloc
91      #define xstrdup checking_strdup
92      #define xfree checking_free
93
94    In case of memory debugging, the definitions are a bit more
95    complex, because we want to provide more information, *and* we want
96    to call the debugging code.  (The former is the reason why xmalloc
97    and friends need to be macros in the first place.)  Then it looks
98    like this:
99
100      #define xmalloc(a) debugging_malloc (a, __FILE__, __LINE__)
101      #define xmalloc0(a) debugging_malloc0 (a, __FILE__, __LINE__)
102      #define xrealloc(a, b) debugging_realloc (a, b, __FILE__, __LINE__)
103      #define xstrdup(a) debugging_strdup (a, __FILE__, __LINE__)
104      #define xfree(a) debugging_free (a, __FILE__, __LINE__)
105
106    Each of the debugging_* functions does its magic and calls the
107    corresponding checking_* one.  */
108
109 #ifdef DEBUG_MALLOC
110 # define STATIC_IF_DEBUG static
111 #else
112 # define STATIC_IF_DEBUG
113 #endif
114
115 STATIC_IF_DEBUG void *
116 checking_malloc (size_t size)
117 {
118   void *ptr = malloc (size);
119   if (!ptr)
120     memfatal ("malloc", size);
121   return ptr;
122 }
123
124 STATIC_IF_DEBUG void *
125 checking_malloc0 (size_t size)
126 {
127   /* Using calloc can be faster than malloc+memset because some calloc
128      implementations know when they're dealing with zeroed-out memory
129      from the system and can avoid unnecessary memset.  */
130   void *ptr = calloc (1, size);
131   if (!ptr)
132     memfatal ("calloc", size);
133   return ptr;
134 }
135
136 STATIC_IF_DEBUG void *
137 checking_realloc (void *ptr, size_t newsize)
138 {
139   void *newptr;
140
141   /* Not all Un*xes have the feature of realloc() that calling it with
142      a NULL-pointer is the same as malloc(), but it is easy to
143      simulate.  */
144   if (ptr)
145     newptr = realloc (ptr, newsize);
146   else
147     newptr = malloc (newsize);
148   if (!newptr)
149     memfatal ("realloc", newsize);
150   return newptr;
151 }
152
153 STATIC_IF_DEBUG char *
154 checking_strdup (const char *s)
155 {
156   char *copy;
157
158 #ifndef HAVE_STRDUP
159   int l = strlen (s);
160   copy = malloc (l + 1);
161   if (!copy)
162     memfatal ("strdup", l + 1);
163   memcpy (copy, s, l + 1);
164 #else  /* HAVE_STRDUP */
165   copy = strdup (s);
166   if (!copy)
167     memfatal ("strdup", 1 + strlen (s));
168 #endif /* HAVE_STRDUP */
169
170   return copy;
171 }
172
173 STATIC_IF_DEBUG void
174 checking_free (void *ptr)
175 {
176   /* Wget's xfree() must not be passed a NULL pointer.  This is for
177      historical reasons: pre-C89 systems were reported to bomb at
178      free(NULL), and Wget was careful to not call xfree when there was
179      a possibility of PTR being NULL.  (It might have been better to
180      simply have xfree() do nothing if ptr==NULL.)
181
182      Since the code is already written that way, this assert simply
183      enforces the existing constraint.  The benefit is double-checking
184      the logic: code that thinks it can't be passed a NULL pointer,
185      while it in fact can, aborts here.  If you trip on this, either
186      the code has a pointer handling bug or should have called
187      xfree_null instead of xfree.  Correctly written code should never
188      trigger this assertion.
189
190      The downside is that the uninitiated might not expect xfree(NULL)
191      to abort.  If the assertion proves to be too much of a hassle, it
192      can be removed and a check that makes NULL a no-op placed in its
193      stead.  If that is done, xfree_null is no longer needed and
194      should be removed.  */
195   assert (ptr != NULL);
196
197   free (ptr);
198 }
199 \f
200 #ifdef DEBUG_MALLOC
201
202 /* Crude home-grown routines for debugging some malloc-related
203    problems.  Featured:
204
205    * Counting the number of malloc and free invocations, and reporting
206      the "balance", i.e. how many times more malloc was called than it
207      was the case with free.
208
209    * Making malloc store its entry into a simple array and free remove
210      stuff from that array.  At the end, print the pointers which have
211      not been freed, along with the source file and the line number.
212
213    * Checking for "invalid frees", where free is called on a pointer
214      not obtained with malloc, or where the same pointer is freed
215      twice.
216
217    Note that this kind of memory leak checking strongly depends on
218    every malloc() being followed by a free(), even if the program is
219    about to finish.  Wget is careful to free the data structure it
220    allocated in init.c.  */
221
222 static int malloc_count, free_count;
223
224 /* Home-grown hash table of mallocs: */
225
226 #define SZ 100003               /* Prime just over 100,000.  Increase
227                                    it to debug larger Wget runs.  */
228
229 static struct {
230   const void *ptr;
231   const char *file;
232   int line;
233 } malloc_table[SZ];
234
235 /* Find PTR's position in malloc_table.  If PTR is not found, return
236    the next available position.  */
237
238 static inline int
239 ptr_position (const void *ptr)
240 {
241   int i = hash_pointer (ptr) % SZ;
242   for (; malloc_table[i].ptr != NULL; i = (i + 1) % SZ)
243     if (malloc_table[i].ptr == ptr)
244       return i;
245   return i;
246 }
247
248 /* Register PTR in malloc_table.  Abort if this is not possible
249    (presumably due to the number of current allocations exceeding the
250    size of malloc_table.)  */
251
252 static void
253 register_ptr (const void *ptr, const char *file, int line)
254 {
255   int i;
256   if (malloc_count - free_count > SZ)
257     {
258       fprintf (stderr, "Increase SZ to a larger value and recompile.\n");
259       fflush (stderr);
260       abort ();
261     }
262
263   i = ptr_position (ptr);
264   malloc_table[i].ptr = ptr;
265   malloc_table[i].file = file;
266   malloc_table[i].line = line;
267 }
268
269 /* Unregister PTR from malloc_table.  Return false if PTR is not
270    present in malloc_table.  */
271
272 static bool
273 unregister_ptr (void *ptr)
274 {
275   int i = ptr_position (ptr);
276   if (malloc_table[i].ptr == NULL)
277     return false;
278   malloc_table[i].ptr = NULL;
279
280   /* Relocate malloc_table entries immediately following PTR. */
281   for (i = (i + 1) % SZ; malloc_table[i].ptr != NULL; i = (i + 1) % SZ)
282     {
283       const void *ptr2 = malloc_table[i].ptr;
284       /* Find the new location for the key. */
285       int j = hash_pointer (ptr2) % SZ;
286       for (; malloc_table[j].ptr != NULL; j = (j + 1) % SZ)
287         if (ptr2 == malloc_table[j].ptr)
288           /* No need to relocate entry at [i]; it's already at or near
289              its hash position. */
290           goto cont_outer;
291       malloc_table[j] = malloc_table[i];
292       malloc_table[i].ptr = NULL;
293     cont_outer:
294       ;
295     }
296   return true;
297 }
298
299 /* Print the malloc debug stats gathered from the above information.
300    Currently this is the count of mallocs, frees, the difference
301    between the two, and the dump of the contents of malloc_table.  The
302    last part are the memory leaks.  */
303
304 void
305 print_malloc_debug_stats (void)
306 {
307   int i;
308   printf ("\nMalloc:  %d\nFree:    %d\nBalance: %d\n\n",
309           malloc_count, free_count, malloc_count - free_count);
310   for (i = 0; i < SZ; i++)
311     if (malloc_table[i].ptr != NULL)
312       printf ("0x%0*lx: %s:%d\n", PTR_FORMAT (malloc_table[i].ptr),
313               malloc_table[i].file, malloc_table[i].line);
314 }
315
316 void *
317 debugging_malloc (size_t size, const char *source_file, int source_line)
318 {
319   void *ptr = checking_malloc (size);
320   ++malloc_count;
321   register_ptr (ptr, source_file, source_line);
322   return ptr;
323 }
324
325 void *
326 debugging_malloc0 (size_t size, const char *source_file, int source_line)
327 {
328   void *ptr = checking_malloc0 (size);
329   ++malloc_count;
330   register_ptr (ptr, source_file, source_line);
331   return ptr;
332 }
333
334 void *
335 debugging_realloc (void *ptr, size_t newsize, const char *source_file, int source_line)
336 {
337   void *newptr = checking_realloc (ptr, newsize);
338   if (!ptr)
339     {
340       ++malloc_count;
341       register_ptr (newptr, source_file, source_line);
342     }
343   else if (newptr != ptr)
344     {
345       unregister_ptr (ptr);
346       register_ptr (newptr, source_file, source_line);
347     }
348   return newptr;
349 }
350
351 char *
352 debugging_strdup (const char *s, const char *source_file, int source_line)
353 {
354   char *copy = checking_strdup (s);
355   ++malloc_count;
356   register_ptr (copy, source_file, source_line);
357   return copy;
358 }
359
360 void
361 debugging_free (void *ptr, const char *source_file, int source_line)
362 {
363   /* See checking_free for rationale of this abort.  We repeat it here
364      because we can print the file and the line where the offending
365      free occurred.  */
366   if (ptr == NULL)
367     {
368       fprintf (stderr, "%s: xfree(NULL) at %s:%d\n",
369                exec_name, source_file, source_line);
370       abort ();
371     }
372   if (!unregister_ptr (ptr))
373     {
374       fprintf (stderr, "%s: bad xfree(0x%0*lx) at %s:%d\n",
375                exec_name, PTR_FORMAT (ptr), source_file, source_line);
376       abort ();
377     }
378   ++free_count;
379
380   checking_free (ptr);
381 }
382
383 #endif /* DEBUG_MALLOC */