-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmanpage.txt
264 lines (186 loc) · 13.5 KB
/
manpage.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
SMALLOC(3) BSD Library Functions Manual SMALLOC(3)
NAME
smalloc : sm_malloc, sm_zalloc, sm_free, sm_realloc, sm_realloc_move, sm_calloc, sm_szalloc — allocate, manage,
resize, query size and free dynamic memory which is allocated from user pointed static memory area;
sm_alloc_valid - query object validity;
sm_malloc_stats - get attached pool statistics;
sm_set_default_pool, sm_release_default_pool - attach and release pool;
sm_set_ub_handler - set global smalloc undefined behavior handler.
SYNOPSIS
#include <errno.h>
#include <smalloc.h>
void *sm_malloc(size_t n);
void *sm_zalloc(size_t n);
void sm_free(void *p);
void *sm_realloc(void *p, size_t n);
void *sm_realloc_move(void *p, size_t n);
void *sm_calloc(size_t y, size_t x);
size_t sm_szalloc(void *p);
int sm_alloc_valid(void *p);
int sm_malloc_stats(size_t *total, size_t *user, size_t *free, int *nr_obj);
int sm_set_default_pool(void *pool, size_t pool_size, int do_zero, smalloc_oom_handler oom_handler_fn);
int sm_release_default_pool(void);
void sm_set_ub_handler(smalloc_ub_handler ub_handler);
DESCRIPTION
smalloc is a portable and simple memory management package which is intended to be used especially with user
provided memory regions. It is like a normal malloc(3) provided by any modern system today (and you should ex‐
pect conventional behavior), but it extends it by allowing the user to specify memory area, a custom heap, in
which all the allocations will be stored.
sm_malloc, sm_zalloc, sm_calloc allocate memory. sm_zalloc and sm_calloc guarantee zero-fill of newly created
object. sm_malloc may return object containing garbage (usually, if pool is static storage, it contains zeroes
after program start, but after extensive usage it will contain garbage).
sm_realloc change already allocated object size, but also can be used to allocate and free memory too.
sm_realloc_move works like sm_realloc, but fails if physical reallocation (move) of the object is required.
sm_free deallocates smalloc allocated memory.
sm_szalloc queries a valid smalloc memory block size.
sm_alloc_valid tests if a pointer belongs to valid smalloc object within the pool.
sm_malloc_stats accept four pointers to numbers where it stores current pool state: *total accepts total used
bytes in pool: user data with any overhead added by smalloc, *user accepts total user bytes with any user over‐
head, *free accepts total free bytes still available, and *nr_obj accepts number of already allocated objects
within the pool.
sm_set_default_pool takes *pool pool of pool_size size and registers it as a global default pool. Nonzero
do_zero instructs smalloc to zero-fill pool before use, and also zero any newly allocated objects before
returning them, and zero any to be freed objects upon to returning them back to the pool. If do_zero is 0, then
only sm_zalloc and sm_calloc zero-fill object before returning them to caller, but sm_malloc will return object
possibly containing garbage. oom_handler_fn can be either NULL or a pointer to OOM handler function (see ERROR
HANDLERS for a description). In case of NULL, no OOM handler is called at all on an OOM condition.
sm_release_default_pool deregisters current pool and zero-fills it (erases) if do_zero argument to
sm_set_default_pool was nonzero. All further calls to any allocation or freeing functions will fail without reg‐
istered pool.
sm_set_ub_handler sets global undefined behavior handler. It's description is given in ERROR HANDLERS section.
If NULL is passed as ub_handler, then internal UB handler is reset to smalloc default one: crashing the program.
RETURN VALUE
sm_malloc, sm_zalloc, sm_calloc return a pointer to newly created object on success. The data it poins to can be
used only up to n argument passed to them (or y * x in case of sm_calloc) If n is 0, these functions return a
pointer to newly created object which content should be never accessed. They return NULL on failure to allocate
memory and set errno to ENOMEM.
sm_realloc returns a pointer to object which size was adjusted. The object address may differ from passed in
address. If p is NULL, then the call is equivalent to sm_malloc(n). If p is a pointer to existing object and n
is 0, then the call is equivalent to sm_free(p). On failure to relocate or size change, it will return NULL and
set errno to ENOMEM.
sm_realloc_move works exactly as sm_realloc, but fails if physical reallocation (move) of the object is re‐
quired. In such case, NULL is returned and errno is set to ERANGE. Original object of question is not touched,
it's size is not changed and it can be used as before.
sm_free does not return a value, but may change errno in cases described in NOTES section.
sm_szalloc return an exact object size of object pointed to by p (the argument n passed to any of: sm_malloc,
sm_zalloc, sm_realloc, sm_realloc_move and y * x result of sm_calloc) This is the only permitted area that the
caller may use. For NULL as argument, sm_szalloc returns 0. For unique object of 0 size created with
sm_malloc(0) (or equivalent), the return value is 1, but this may be changed in future.
sm_alloc_valid returns 1 if object pointed to by p is valid reference, 0 otherwise. It does not permit to dif‐
ferentiate between multiple pools.
sm_malloc_stats return 1 when the pool contains at least one object, thus numbers stored are not zeroes, 0 if no
objects are in pool or all arguments are NULLs, or -1 on any other error described in NOTES section.
sm_set_default_pool returns 1 on success (pool was registered), 0 if pool is very small to use. In this situa‐
tion, an errno will be also set to ENOSPC.
sm_release_default_pool returns 1 on success (an existing pool was successfully deregistered), 0 otherwise, with
errno set to EINVAL.
sm_set_ub_handler always succeeds and does not return any value.
NOTES
If pool was never registered, or recently was deregistered with sm_release_default_pool, then all memory manage‐
ment functions will fail by returning their error values: NULL or 0 or -1 or (size_t)-1, or (void) and errno
will be set to EINVAL.
All functions working on existing objects which take pointers to them, except sm_alloc_valid, will check the
pointer to be a valid reference to existing object belonging to registered pool. If an invalid pointer is
catched, then smalloc calls an undefined behavior handler. The default smalloc embedded UB handler is set to
crash the program to bring programmer's attention as early as possible. This handler can be overriden with
sm_set_ub_handler for a lifetime of program until next call to this function. sm_alloc_valid does not call UB
handler in case of invalid pointer reference: it was specially designed to answer the question: “Is this pointer
a valid object reference?”
One can implement a classic but more precise malloc on top of smalloc by using brk(2) as a custom heap and ex‐
tending it on each OOM handler call.
ERROR HANDLERS
smalloc_oom_handler Out Of Memory handler is defined as follows:
typedef size_t (*smalloc_oom_handler)(struct smalloc_pool *, size_t);
size_t oom_handler(struct smalloc_pool *spool, size_t failed_alloc_req);
It takes a pool descriptor *spool (see MULTIPLE POOLS section) and failed_alloc_req, which is size of object
that failed to be created (the n argument to allocation functions). The task of OOM handler is either to report
an abnormal condition, possibly (and often) with program abortion or other way to exit, or to extend the pool,
if possible (if pool is static, but resizeable). In case of refuse to extend, but without abortion, the handler
must return 0. Otherwise handler must return a new size of pool after successful extension.
IMPORTANT! The pool CANNOT BE RELOCATED IF IT CONTAINS ALLOCATED OBJECTS with functions such as realloc(3). Re‐
location of pool will lead to bad references to the objects stored inside pointers across your program! You must
ensure that pool will never be relocated once used when resizing the pool. Returning a size lesser than current
pool size will not lead to extension of pool, the effect will be the same as if handler would return 0. Returned
size may or may not be not aligned: the function will align the new size automatically.
smalloc_ub_handler Undefined Behavior handler is defined as follows:
typedef void (*smalloc_ub_handler)(struct smalloc_pool *, const void *);
void ub_handler(struct smalloc_pool *spool, const void *offender);
It takes a pool descriptor *spool (see MULTIPLE POOLS section) and *offender pointer which is an exact pointer
value that caused an UB exception. The task of UB handler is to report the condition as fast as possible and
abort the program. An UB handler can ignore abnormal condition, but it is highly discouraged. Default UB han‐
dler embedded into smalloc itself is to cause program crash by writing to NULL pointer. It does not report con‐
dition somewhere just not to depend on libc's stdio package (or something other, possibly platform specific).
MULTIPLE POOLS
smalloc supports using multiple pools in parallel (but not in multithreaded environment however). There are ver‐
sions of described functions above which names end with ‘_pool’ suffix and have prepended their first argument
as struct smalloc_pool *, which is a pool descriptor of this format:
struct smalloc_pool {
void *pool;
size_t pool_size;
int do_zero;
smalloc_oom_handler oomfn;
};
Manual fill of the structure is NOT RECOMMENDED, it is best to use a pool aware sm_set_pool function, which is
just the sm_set_default_pool variant with struct smalloc_pool * as it's first argument.
Releasing such a pool is done with sm_release_pool, which takes struct smalloc_pool * as it's only single argu‐
ment.
Memory behind these descriptors is not allocated by smalloc, it is task of the caller to store pool descriptors
somewhere.
Then caller may turn normal functions into pool versions, for example: sm_realloc(void *p, size_t n) turns into
sm_realloc_pool(struct smalloc_pool *spool, void *p, size_t n), and so on.
There is a sm_align_pool function, which takes a pool descriptor and adjusts it's pool_size member to a value
best fit for a smalloc. This function is provided only for manual fill of the pool descriptor. Unaligned pool
descriptors will be rejected by smalloc and errno will be set to EINVAL in such cases.
smalloc_curr_pool symbol points to global pool descriptor which is used by sm_set_default_pool and
sm_release_default_pool, as well as by ‘non-pool’ functions.
FILES
See smalloc.h, smalloc_test_so.c, and source code.
EXAMPLE
This is the minimal example of how to use the library:
#include <smalloc.h>
static char my_pool[16384];
int main(void)
{
char *s, *d;
size_t n;
if (!sm_set_default_pool(my_pool, sizeof(my_pool), 0, NULL)) return 1;
s = sm_malloc(40);
if (s) {
n = sm_szalloc(s);
memset(s, 'X', n);
}
d = sm_malloc(700);
if (d) memset(d, 'Y', sm_szalloc(d));
s = sm_realloc(s, n+30);
if (s) memset(s+n, 'x', sm_szalloc(s)-n);
d = sm_realloc(d, 14000);
if (d) memset(d, 'y', sm_szalloc(d));
sm_free(s);
sm_free(d);
sm_release_default_pool();
return 0;
}
BUGS
Returned objects may or may not be aligned to be used for any kind of variable. However it places objects ex‐
actly so at least integers and pointers can be placed and used without harm within them.
Allocations lesser than 12 bytes on 32 bit systems (typ.) are not so efficient: the object header takes 12 bytes
and minimum overhead size is also 12 bytes. So per each, for example, 4 byte request there will be a 20 byte of
overhead. On 64 bit systems it's even worse, things usually double.
True multithreading with locking was not implemented and is not currently a planned task.
Unlike highly promoted Linux's behavior about always succeeding malloc, the memory in smalloc is managed di‐
rectly by programmer.
CONFORMING TO
sm_malloc, sm_calloc, sm_realloc and sm_free are fully compatible with usual malloc, calloc, realloc and free.
Their behavior on normal/failed situations is same (or should be same - report a bug if not). Programmer should
not bother about UB because good program does not invoke UB.
sm_zalloc, sm_szalloc, sm_realloc_move and sm_alloc_valid are smalloc extensions. They're not implemented in
other malloc type packages, thus their usage is not portable.
AUTHORS
smalloc was written in spare time by Andrey Rys <[email protected]> for his own access(8) program. This library is
available at https://github.com/lynxlynx/smalloc/, and access(8) is available at
https://github.com/lynxlynx/access/.
The code, unlike any other programs written by Rys is MIT licensed: Copyright (c) 2017 Andrey Rys
<[email protected]>. See COPYRIGHT file in the source distribution for complete terms.
SEE ALSO
malloc(3), calloc(3), free(3), realloc(3).
R2 October 11, 2020 R2