FFmpeg  4.3
mem.c
Go to the documentation of this file.
1 /*
2  * default memory allocator for libavutil
3  * Copyright (c) 2002 Fabrice Bellard
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg 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 GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /**
23  * @file
24  * default memory allocator for libavutil
25  */
26 
27 #define _XOPEN_SOURCE 600
28 
29 #include "config.h"
30 
31 #include <limits.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #if HAVE_MALLOC_H
36 #include <malloc.h>
37 #endif
38 
39 #include "avassert.h"
40 #include "avutil.h"
41 #include "common.h"
42 #include "dynarray.h"
43 #include "intreadwrite.h"
44 #include "mem.h"
45 
46 #ifdef MALLOC_PREFIX
47 
48 #define malloc AV_JOIN(MALLOC_PREFIX, malloc)
49 #define memalign AV_JOIN(MALLOC_PREFIX, memalign)
50 #define posix_memalign AV_JOIN(MALLOC_PREFIX, posix_memalign)
51 #define realloc AV_JOIN(MALLOC_PREFIX, realloc)
52 #define free AV_JOIN(MALLOC_PREFIX, free)
53 
54 void *malloc(size_t size);
55 void *memalign(size_t align, size_t size);
56 int posix_memalign(void **ptr, size_t align, size_t size);
57 void *realloc(void *ptr, size_t size);
58 void free(void *ptr);
59 
60 #endif /* MALLOC_PREFIX */
61 
62 #include "mem_internal.h"
63 
64 #define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16))
65 
66 /* NOTE: if you want to override these functions with your own
67  * implementations (not recommended) you have to link libav* as
68  * dynamic libraries and remove -Wl,-Bsymbolic from the linker flags.
69  * Note that this will cost performance. */
70 
71 static size_t max_alloc_size= INT_MAX;
72 
73 void av_max_alloc(size_t max){
75 }
76 
77 void *av_malloc(size_t size)
78 {
79  void *ptr = NULL;
80 
81  /* let's disallow possibly ambiguous cases */
82  if (size > (max_alloc_size - 32))
83  return NULL;
84 
85 #if HAVE_POSIX_MEMALIGN
86  if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
87  if (posix_memalign(&ptr, ALIGN, size))
88  ptr = NULL;
89 #elif HAVE_ALIGNED_MALLOC
90  ptr = _aligned_malloc(size, ALIGN);
91 #elif HAVE_MEMALIGN
92 #ifndef __DJGPP__
93  ptr = memalign(ALIGN, size);
94 #else
95  ptr = memalign(size, ALIGN);
96 #endif
97  /* Why 64?
98  * Indeed, we should align it:
99  * on 4 for 386
100  * on 16 for 486
101  * on 32 for 586, PPro - K6-III
102  * on 64 for K7 (maybe for P3 too).
103  * Because L1 and L2 caches are aligned on those values.
104  * But I don't want to code such logic here!
105  */
106  /* Why 32?
107  * For AVX ASM. SSE / NEON needs only 16.
108  * Why not larger? Because I did not see a difference in benchmarks ...
109  */
110  /* benchmarks with P3
111  * memalign(64) + 1 3071, 3051, 3032
112  * memalign(64) + 2 3051, 3032, 3041
113  * memalign(64) + 4 2911, 2896, 2915
114  * memalign(64) + 8 2545, 2554, 2550
115  * memalign(64) + 16 2543, 2572, 2563
116  * memalign(64) + 32 2546, 2545, 2571
117  * memalign(64) + 64 2570, 2533, 2558
118  *
119  * BTW, malloc seems to do 8-byte alignment by default here.
120  */
121 #else
122  ptr = malloc(size);
123 #endif
124  if(!ptr && !size) {
125  size = 1;
126  ptr= av_malloc(1);
127  }
128 #if CONFIG_MEMORY_POISONING
129  if (ptr)
130  memset(ptr, FF_MEMORY_POISON, size);
131 #endif
132  return ptr;
133 }
134 
135 void *av_realloc(void *ptr, size_t size)
136 {
137  /* let's disallow possibly ambiguous cases */
138  if (size > (max_alloc_size - 32))
139  return NULL;
140 
141 #if HAVE_ALIGNED_MALLOC
142  return _aligned_realloc(ptr, size + !size, ALIGN);
143 #else
144  return realloc(ptr, size + !size);
145 #endif
146 }
147 
148 void *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
149 {
150  size_t size;
151  void *r;
152 
153  if (av_size_mult(elsize, nelem, &size)) {
154  av_free(ptr);
155  return NULL;
156  }
157  r = av_realloc(ptr, size);
158  if (!r)
159  av_free(ptr);
160  return r;
161 }
162 
163 int av_reallocp(void *ptr, size_t size)
164 {
165  void *val;
166 
167  if (!size) {
168  av_freep(ptr);
169  return 0;
170  }
171 
172  memcpy(&val, ptr, sizeof(val));
173  val = av_realloc(val, size);
174 
175  if (!val) {
176  av_freep(ptr);
177  return AVERROR(ENOMEM);
178  }
179 
180  memcpy(ptr, &val, sizeof(val));
181  return 0;
182 }
183 
184 void *av_malloc_array(size_t nmemb, size_t size)
185 {
186  size_t result;
187  if (av_size_mult(nmemb, size, &result) < 0)
188  return NULL;
189  return av_malloc(result);
190 }
191 
192 void *av_mallocz_array(size_t nmemb, size_t size)
193 {
194  size_t result;
195  if (av_size_mult(nmemb, size, &result) < 0)
196  return NULL;
197  return av_mallocz(result);
198 }
199 
200 void *av_realloc_array(void *ptr, size_t nmemb, size_t size)
201 {
202  size_t result;
203  if (av_size_mult(nmemb, size, &result) < 0)
204  return NULL;
205  return av_realloc(ptr, result);
206 }
207 
208 int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
209 {
210  void *val;
211 
212  memcpy(&val, ptr, sizeof(val));
213  val = av_realloc_f(val, nmemb, size);
214  memcpy(ptr, &val, sizeof(val));
215  if (!val && nmemb && size)
216  return AVERROR(ENOMEM);
217 
218  return 0;
219 }
220 
221 void av_free(void *ptr)
222 {
223 #if HAVE_ALIGNED_MALLOC
224  _aligned_free(ptr);
225 #else
226  free(ptr);
227 #endif
228 }
229 
230 void av_freep(void *arg)
231 {
232  void *val;
233 
234  memcpy(&val, arg, sizeof(val));
235  memcpy(arg, &(void *){ NULL }, sizeof(val));
236  av_free(val);
237 }
238 
239 void *av_mallocz(size_t size)
240 {
241  void *ptr = av_malloc(size);
242  if (ptr)
243  memset(ptr, 0, size);
244  return ptr;
245 }
246 
247 void *av_calloc(size_t nmemb, size_t size)
248 {
249  size_t result;
250  if (av_size_mult(nmemb, size, &result) < 0)
251  return NULL;
252  return av_mallocz(result);
253 }
254 
255 char *av_strdup(const char *s)
256 {
257  char *ptr = NULL;
258  if (s) {
259  size_t len = strlen(s) + 1;
260  ptr = av_realloc(NULL, len);
261  if (ptr)
262  memcpy(ptr, s, len);
263  }
264  return ptr;
265 }
266 
267 char *av_strndup(const char *s, size_t len)
268 {
269  char *ret = NULL, *end;
270 
271  if (!s)
272  return NULL;
273 
274  end = memchr(s, 0, len);
275  if (end)
276  len = end - s;
277 
278  ret = av_realloc(NULL, len + 1);
279  if (!ret)
280  return NULL;
281 
282  memcpy(ret, s, len);
283  ret[len] = 0;
284  return ret;
285 }
286 
287 void *av_memdup(const void *p, size_t size)
288 {
289  void *ptr = NULL;
290  if (p) {
291  ptr = av_malloc(size);
292  if (ptr)
293  memcpy(ptr, p, size);
294  }
295  return ptr;
296 }
297 
298 int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
299 {
300  void **tab;
301  memcpy(&tab, tab_ptr, sizeof(tab));
302 
303  FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
304  tab[*nb_ptr] = elem;
305  memcpy(tab_ptr, &tab, sizeof(tab));
306  }, {
307  return AVERROR(ENOMEM);
308  });
309  return 0;
310 }
311 
312 void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
313 {
314  void **tab;
315  memcpy(&tab, tab_ptr, sizeof(tab));
316 
317  FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
318  tab[*nb_ptr] = elem;
319  memcpy(tab_ptr, &tab, sizeof(tab));
320  }, {
321  *nb_ptr = 0;
322  av_freep(tab_ptr);
323  });
324 }
325 
326 void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
327  const uint8_t *elem_data)
328 {
329  uint8_t *tab_elem_data = NULL;
330 
331  FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {
332  tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
333  if (elem_data)
334  memcpy(tab_elem_data, elem_data, elem_size);
335  else if (CONFIG_MEMORY_POISONING)
336  memset(tab_elem_data, FF_MEMORY_POISON, elem_size);
337  }, {
338  av_freep(tab_ptr);
339  *nb_ptr = 0;
340  });
341  return tab_elem_data;
342 }
343 
344 static void fill16(uint8_t *dst, int len)
345 {
346  uint32_t v = AV_RN16(dst - 2);
347 
348  v |= v << 16;
349 
350  while (len >= 4) {
351  AV_WN32(dst, v);
352  dst += 4;
353  len -= 4;
354  }
355 
356  while (len--) {
357  *dst = dst[-2];
358  dst++;
359  }
360 }
361 
362 static void fill24(uint8_t *dst, int len)
363 {
364 #if HAVE_BIGENDIAN
365  uint32_t v = AV_RB24(dst - 3);
366  uint32_t a = v << 8 | v >> 16;
367  uint32_t b = v << 16 | v >> 8;
368  uint32_t c = v << 24 | v;
369 #else
370  uint32_t v = AV_RL24(dst - 3);
371  uint32_t a = v | v << 24;
372  uint32_t b = v >> 8 | v << 16;
373  uint32_t c = v >> 16 | v << 8;
374 #endif
375 
376  while (len >= 12) {
377  AV_WN32(dst, a);
378  AV_WN32(dst + 4, b);
379  AV_WN32(dst + 8, c);
380  dst += 12;
381  len -= 12;
382  }
383 
384  if (len >= 4) {
385  AV_WN32(dst, a);
386  dst += 4;
387  len -= 4;
388  }
389 
390  if (len >= 4) {
391  AV_WN32(dst, b);
392  dst += 4;
393  len -= 4;
394  }
395 
396  while (len--) {
397  *dst = dst[-3];
398  dst++;
399  }
400 }
401 
402 static void fill32(uint8_t *dst, int len)
403 {
404  uint32_t v = AV_RN32(dst - 4);
405 
406 #if HAVE_FAST_64BIT
407  uint64_t v2= v + ((uint64_t)v<<32);
408  while (len >= 32) {
409  AV_WN64(dst , v2);
410  AV_WN64(dst+ 8, v2);
411  AV_WN64(dst+16, v2);
412  AV_WN64(dst+24, v2);
413  dst += 32;
414  len -= 32;
415  }
416 #endif
417 
418  while (len >= 4) {
419  AV_WN32(dst, v);
420  dst += 4;
421  len -= 4;
422  }
423 
424  while (len--) {
425  *dst = dst[-4];
426  dst++;
427  }
428 }
429 
430 void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
431 {
432  const uint8_t *src = &dst[-back];
433  if (!back)
434  return;
435 
436  if (back == 1) {
437  memset(dst, *src, cnt);
438  } else if (back == 2) {
439  fill16(dst, cnt);
440  } else if (back == 3) {
441  fill24(dst, cnt);
442  } else if (back == 4) {
443  fill32(dst, cnt);
444  } else {
445  if (cnt >= 16) {
446  int blocklen = back;
447  while (cnt > blocklen) {
448  memcpy(dst, src, blocklen);
449  dst += blocklen;
450  cnt -= blocklen;
451  blocklen <<= 1;
452  }
453  memcpy(dst, src, cnt);
454  return;
455  }
456  if (cnt >= 8) {
457  AV_COPY32U(dst, src);
458  AV_COPY32U(dst + 4, src + 4);
459  src += 8;
460  dst += 8;
461  cnt -= 8;
462  }
463  if (cnt >= 4) {
464  AV_COPY32U(dst, src);
465  src += 4;
466  dst += 4;
467  cnt -= 4;
468  }
469  if (cnt >= 2) {
470  AV_COPY16U(dst, src);
471  src += 2;
472  dst += 2;
473  cnt -= 2;
474  }
475  if (cnt)
476  *dst = *src;
477  }
478 }
479 
480 void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
481 {
482  if (min_size <= *size)
483  return ptr;
484 
485  if (min_size > max_alloc_size - 32) {
486  *size = 0;
487  return NULL;
488  }
489 
490  min_size = FFMIN(max_alloc_size - 32, FFMAX(min_size + min_size / 16 + 32, min_size));
491 
492  ptr = av_realloc(ptr, min_size);
493  /* we could set this to the unmodified min_size but this is safer
494  * if the user lost the ptr and uses NULL now
495  */
496  if (!ptr)
497  min_size = 0;
498 
499  *size = min_size;
500 
501  return ptr;
502 }
503 
504 void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
505 {
506  ff_fast_malloc(ptr, size, min_size, 0);
507 }
508 
509 void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
510 {
511  ff_fast_malloc(ptr, size, min_size, 1);
512 }
FF_DYNARRAY_ADD
#define FF_DYNARRAY_ADD(av_size_max, av_elt_size, av_array, av_size, av_success, av_failure)
Add an element to a dynamic array.
Definition: dynarray.h:45
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
mem_internal.h
max_alloc_size
static size_t max_alloc_size
Definition: mem.c:71
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
AV_RN16
#define AV_RN16(p)
Definition: intreadwrite.h:360
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
ff_fast_malloc
static int ff_fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc)
Definition: mem_internal.h:27
av_dynarray2_add
void * av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data)
Add an element of size elem_size to a dynamic array.
Definition: mem.c:326
b
#define b
Definition: input.c:41
FF_MEMORY_POISON
#define FF_MEMORY_POISON
Definition: internal.h:89
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Allocate a memory block for an array with av_mallocz().
Definition: mem.c:192
av_malloc
void * av_malloc(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:77
max
#define max(a, b)
Definition: cuda_runtime.h:33
av_memdup
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition: mem.c:287
av_max_alloc
void av_max_alloc(size_t max)
Set the maximum size that may be allocated in one block.
Definition: mem.c:73
av_realloc_f
void * av_realloc_f(void *ptr, size_t nelem, size_t elsize)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:148
fill16
static void fill16(uint8_t *dst, int len)
Definition: mem.c:344
tab
static const struct twinvq_data tab
Definition: twinvq_data.h:11135
val
static double val(void *priv, double ch)
Definition: aeval.c:76
AV_RB24
#define AV_RB24
Definition: intreadwrite.h:64
avassert.h
AV_COPY32U
#define AV_COPY32U(d, s)
Definition: intreadwrite.h:572
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:430
av_malloc_array
void * av_malloc_array(size_t nmemb, size_t size)
Allocate a memory block for an array with av_malloc().
Definition: mem.c:184
av_fast_realloc
void * av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
Reallocate the given buffer if it is not large enough, otherwise do nothing.
Definition: mem.c:480
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array.
Definition: mem.c:200
av_freep
void av_freep(void *arg)
Free a memory block which has been allocated with a function of av_malloc() or av_realloc() family,...
Definition: mem.c:230
AV_COPY16U
#define AV_COPY16U(d, s)
Definition: intreadwrite.h:568
av_size_mult
static int av_size_mult(size_t a, size_t b, size_t *r)
Multiply two size_t values checking for overflow.
Definition: mem.h:669
limits.h
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:239
arg
const char * arg
Definition: jacosubdec.c:66
ALIGN
#define ALIGN
Definition: mem.c:64
fill24
static void fill24(uint8_t *dst, int len)
Definition: mem.c:362
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
NULL
#define NULL
Definition: coverity.c:32
CONFIG_MEMORY_POISONING
#define CONFIG_MEMORY_POISONING
Definition: config.h:589
AV_RN32
#define AV_RN32(p)
Definition: intreadwrite.h:364
src
#define src
Definition: vp8dsp.c:254
av_fast_mallocz
void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
Allocate and clear a buffer, reusing the given one if large enough.
Definition: mem.c:509
AV_RL24
#define AV_RL24
Definition: intreadwrite.h:78
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
av_dynarray_add
void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
Add the pointer to an element to a dynamic array.
Definition: mem.c:312
AV_WN32
#define AV_WN32(p, v)
Definition: intreadwrite.h:376
FFMAX
#define FFMAX(a, b)
Definition: common.h:94
size
int size
Definition: twinvq_data.h:11134
av_reallocp
int av_reallocp(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory through a pointer to a pointer.
Definition: mem.c:163
fill32
static void fill32(uint8_t *dst, int len)
Definition: mem.c:402
FFMIN
#define FFMIN(a, b)
Definition: common.h:96
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
av_reallocp_array
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array through a pointer to a pointer.
Definition: mem.c:208
r
#define r
Definition: input.c:40
common.h
uint8_t
uint8_t
Definition: audio_convert.c:194
len
int len
Definition: vorbis_enc_data.h:452
av_free
void av_free(void *ptr)
Free a memory block which has been allocated with a function of av_malloc() or av_realloc() family.
Definition: mem.c:221
ret
ret
Definition: filter_design.txt:187
dynarray.h
av_dynarray_add_nofree
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
Definition: mem.c:298
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:247
config.h
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:255
avutil.h
mem.h
av_fast_malloc
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition: mem.c:504
AV_WN64
#define AV_WN64(p, v)
Definition: intreadwrite.h:380
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:267