sanity_check_size() memory allocations on debug builds only.
[freeciv.git] / utility / mem.c
blob66e81ef2ea50a280e23f3ddf37fa853cfe258716
1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 /**********************************************************************
16 * This module contains freeciv-specific memory management functions
18 **********************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include <fc_config.h>
22 #endif
24 #include <stdlib.h>
25 #include <string.h>
27 /* utility */
28 #include "fcintl.h"
29 #include "log.h"
30 #include "shared.h" /* TRUE, FALSE */
32 #include "mem.h"
34 /**********************************************************************
35 Do whatever we should do when malloc fails.
36 At the moment this just prints a log message and calls exit(EXIT_FAILURE)
37 **********************************************************************/
38 static void handle_alloc_failure(size_t size, const char *called_as,
39 int line, const char *file)
41 log_fatal("Out of memory trying to %s %lu bytes at line %d of %s.",
42 called_as, (unsigned long) size, line, file);
43 exit(EXIT_FAILURE);
46 #ifdef FREECIV_DEBUG
47 /****************************************************************************
48 Check the size for sanity. The program will exit rather than allocate a
49 dangerously large amount of memory.
50 ****************************************************************************/
51 static void sanity_check_size(size_t size, const char *called_as,
52 int line, const char *file)
54 /* There used to be a sanity check here that would abort if more than
55 * 30 megabytes were allocated. Unfortunately this didn't work because
56 * savegame loading can potentially use a huge amount of memory for large
57 * games. Another problem is it doesn't help much because there's nothing
58 * preventing a large number of smaller allocations. */
60 if (size == 0) {
61 log_verbose("Warning: %s with size %lu at line %d of %s",
62 called_as, (unsigned long) size, line, file);
65 #endif /* FREECIV_DEBUG */
67 /*******************************************************************************
68 Function used by fc_malloc macro, malloc() replacement
70 There's no need for the caller to check return value; this function will
71 always return a valid pointer (even for a 0-byte malloc).
72 *******************************************************************************/
73 void *fc_real_malloc(size_t size,
74 const char *called_as, int line, const char *file)
76 void *ptr;
78 #ifdef FREECIV_DEBUG
79 sanity_check_size(size, called_as, line, file);
80 #endif /* FREECIV_DEBUG */
82 /* Some systems return NULL on malloc(0)
83 * According to ANSI C, the return is implementation-specific,
84 * this is a safe guard. Having the extra byte is, of course, harmless. */
85 #ifndef MALLOC_ZERO_OK
86 size = MAX(size, 1);
87 #endif
89 ptr = malloc(size);
90 if (ptr == NULL) {
91 handle_alloc_failure(size, called_as, line, file);
94 return ptr;
97 /**********************************************************************
98 Function used by fc_realloc macro, realloc() replacement
99 No need to check return value.
100 **********************************************************************/
101 void *fc_real_realloc(void *ptr, size_t size,
102 const char *called_as, int line, const char *file)
104 void *new_ptr;
106 if (!ptr) {
107 return fc_real_malloc(size, called_as, line, file);
110 #ifdef FREECIV_DEBUG
111 sanity_check_size(size, called_as, line, file);
112 #endif /* FREECIV_DEBUG */
114 new_ptr = realloc(ptr, size);
115 if (!new_ptr) {
116 handle_alloc_failure(size, called_as, line, file);
118 return new_ptr;
121 /**********************************************************************
122 Function used by fc_calloc macro, calloc() replacement
123 No need to check return value.
125 I'm pretty sure only the product of nelem and elsize can ever
126 matter here, and not their individual values. (As a matter of C.)
127 Except this function doesn't support calloc-ing more memory than
128 can be expressing using a single size_t, but that's not likely
129 to be a problem.
130 **********************************************************************/
131 void *fc_real_calloc(size_t nelem, size_t elsize,
132 const char *called_as, int line, const char *file)
134 size_t size = nelem*elsize; /* potential overflow */
135 void *ptr;
137 ptr = fc_real_malloc(size, called_as, line, file);
138 memset(ptr, 0, size);
139 return ptr;
142 /***************************************************************
143 Function used by fc_strdup macro, strdup() replacement
144 No need to check return value.
145 ***************************************************************/
146 char *real_fc_strdup(const char *str,
147 const char *called_as, int line, const char *file)
149 char *dest = fc_real_malloc(strlen(str)+1, called_as, line, file);
151 /* no need to check whether dest is non-NULL! */
152 strcpy(dest, str);
153 return dest;