1 /**
2  * @file
3  * Memory management wrappers
4  *
5  * @authors
6  * Copyright (C) 2017 Richard Russon <rich@flatcap.org>
7  *
8  * @copyright
9  * This program is free software: you can redistribute it and/or modify it under
10  * the terms of the GNU General Public License as published by the Free Software
11  * Foundation, either version 2 of the License, or (at your option) any later
12  * version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 /**
24  * @page mutt_memory Memory management wrappers
25  *
26  * "Safe" memory management routines.
27  *
28  * @note If any of the allocators fail, the user is notified and the program is
29  *       stopped immediately.
30  */
31 
32 #include "config.h"
33 #include <stdlib.h>
34 #include "memory.h"
35 #include "exit.h"
36 #include "logging.h"
37 #include "message.h"
38 
39 /**
40  * mutt_mem_calloc - Allocate zeroed memory on the heap
41  * @param nmemb Number of blocks
42  * @param size  Size of blocks
43  * @retval ptr Memory on the heap
44  *
45  * @note On error, this function will never return NULL.
46  *       It will print an error and exit the program.
47  *
48  * The caller should call mutt_mem_free() to release the memory
49  */
mutt_mem_calloc(size_t nmemb,size_t size)50 void *mutt_mem_calloc(size_t nmemb, size_t size)
51 {
52   if ((nmemb == 0) || (size == 0))
53     return NULL;
54 
55   void *p = calloc(nmemb, size);
56   if (!p)
57   {
58     mutt_error(_("Out of memory"));
59     mutt_exit(1);
60   }
61   return p;
62 }
63 
64 /**
65  * mutt_mem_free - Release memory allocated on the heap
66  * @param ptr Memory to release
67  */
mutt_mem_free(void * ptr)68 void mutt_mem_free(void *ptr)
69 {
70   if (!ptr)
71     return;
72   void **p = (void **) ptr;
73   if (*p)
74   {
75     free(*p);
76     *p = NULL;
77   }
78 }
79 
80 /**
81  * mutt_mem_malloc - Allocate memory on the heap
82  * @param size Size of block to allocate
83  * @retval ptr Memory on the heap
84  *
85  * @note On error, this function will never return NULL.
86  *       It will print an error and exit the program.
87  *
88  * The caller should call mutt_mem_free() to release the memory
89  */
mutt_mem_malloc(size_t size)90 void *mutt_mem_malloc(size_t size)
91 {
92   if (size == 0)
93     return NULL;
94 
95   void *p = malloc(size);
96   if (!p)
97   {
98     mutt_error(_("Out of memory"));
99     mutt_exit(1);
100   }
101   return p;
102 }
103 
104 /**
105  * mutt_mem_realloc - Resize a block of memory on the heap
106  * @param ptr Memory block to resize
107  * @param size New size
108  *
109  * @note On error, this function will never return NULL.
110  *       It will print an error and exit the program.
111  *
112  * If the new size is zero, the block will be freed.
113  */
mutt_mem_realloc(void * ptr,size_t size)114 void mutt_mem_realloc(void *ptr, size_t size)
115 {
116   if (!ptr)
117     return;
118 
119   void **p = (void **) ptr;
120 
121   if (size == 0)
122   {
123     if (*p)
124     {
125       free(*p);
126       *p = NULL;
127     }
128     return;
129   }
130 
131   void *r = realloc(*p, size);
132   if (!r)
133   {
134     mutt_error(_("Out of memory"));
135     mutt_exit(1);
136   }
137 
138   *p = r;
139 }
140