FFmpeg
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  if (size > max_alloc_size)
82  return NULL;
83 
84 #if HAVE_POSIX_MEMALIGN
85  if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
86  if (posix_memalign(&ptr, ALIGN, size))
87  ptr = NULL;
88 #elif HAVE_ALIGNED_MALLOC
89  ptr = _aligned_malloc(size, ALIGN);
90 #elif HAVE_MEMALIGN
91 #ifndef __DJGPP__
92  ptr = memalign(ALIGN, size);
93 #else
94  ptr = memalign(size, ALIGN);
95 #endif
96  /* Why 64?
97  * Indeed, we should align it:
98  * on 4 for 386
99  * on 16 for 486
100  * on 32 for 586, PPro - K6-III
101  * on 64 for K7 (maybe for P3 too).
102  * Because L1 and L2 caches are aligned on those values.
103  * But I don't want to code such logic here!
104  */
105  /* Why 32?
106  * For AVX ASM. SSE / NEON needs only 16.
107  * Why not larger? Because I did not see a difference in benchmarks ...
108  */
109  /* benchmarks with P3
110  * memalign(64) + 1 3071, 3051, 3032
111  * memalign(64) + 2 3051, 3032, 3041
112  * memalign(64) + 4 2911, 2896, 2915
113  * memalign(64) + 8 2545, 2554, 2550
114  * memalign(64) + 16 2543, 2572, 2563
115  * memalign(64) + 32 2546, 2545, 2571
116  * memalign(64) + 64 2570, 2533, 2558
117  *
118  * BTW, malloc seems to do 8-byte alignment by default here.
119  */
120 #else
121  ptr = malloc(size);
122 #endif
123  if(!ptr && !size) {
124  size = 1;
125  ptr= av_malloc(1);
126  }
127 #if CONFIG_MEMORY_POISONING
128  if (ptr)
129  memset(ptr, FF_MEMORY_POISON, size);
130 #endif
131  return ptr;
132 }
133 
134 void *av_realloc(void *ptr, size_t size)
135 {
136  if (size > max_alloc_size)
137  return NULL;
138 
139 #if HAVE_ALIGNED_MALLOC
140  return _aligned_realloc(ptr, size + !size, ALIGN);
141 #else
142  return realloc(ptr, size + !size);
143 #endif
144 }
145 
146 void *av_realloc_f(void *ptr, size_t nelem, size_t elsize)
147 {
148  size_t size;
149  void *r;
150 
151  if (av_size_mult(elsize, nelem, &size)) {
152  av_free(ptr);
153  return NULL;
154  }
155  r = av_realloc(ptr, size);
156  if (!r)
157  av_free(ptr);
158  return r;
159 }
160 
161 int av_reallocp(void *ptr, size_t size)
162 {
163  void *val;
164 
165  if (!size) {
166  av_freep(ptr);
167  return 0;
168  }
169 
170  memcpy(&val, ptr, sizeof(val));
171  val = av_realloc(val, size);
172 
173  if (!val) {
174  av_freep(ptr);
175  return AVERROR(ENOMEM);
176  }
177 
178  memcpy(ptr, &val, sizeof(val));
179  return 0;
180 }
181 
182 void *av_malloc_array(size_t nmemb, size_t size)
183 {
184  size_t result;
185  if (av_size_mult(nmemb, size, &result) < 0)
186  return NULL;
187  return av_malloc(result);
188 }
189 
190 void *av_mallocz_array(size_t nmemb, size_t size)
191 {
192  size_t result;
193  if (av_size_mult(nmemb, size, &result) < 0)
194  return NULL;
195  return av_mallocz(result);
196 }
197 
198 void *av_realloc_array(void *ptr, size_t nmemb, size_t size)
199 {
200  size_t result;
201  if (av_size_mult(nmemb, size, &result) < 0)
202  return NULL;
203  return av_realloc(ptr, result);
204 }
205 
206 int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
207 {
208  void *val;
209 
210  memcpy(&val, ptr, sizeof(val));
211  val = av_realloc_f(val, nmemb, size);
212  memcpy(ptr, &val, sizeof(val));
213  if (!val && nmemb && size)
214  return AVERROR(ENOMEM);
215 
216  return 0;
217 }
218 
219 void av_free(void *ptr)
220 {
221 #if HAVE_ALIGNED_MALLOC
222  _aligned_free(ptr);
223 #else
224  free(ptr);
225 #endif
226 }
227 
228 void av_freep(void *arg)
229 {
230  void *val;
231 
232  memcpy(&val, arg, sizeof(val));
233  memcpy(arg, &(void *){ NULL }, sizeof(val));
234  av_free(val);
235 }
236 
237 void *av_mallocz(size_t size)
238 {
239  void *ptr = av_malloc(size);
240  if (ptr)
241  memset(ptr, 0, size);
242  return ptr;
243 }
244 
245 void *av_calloc(size_t nmemb, size_t size)
246 {
247  size_t result;
248  if (av_size_mult(nmemb, size, &result) < 0)
249  return NULL;
250  return av_mallocz(result);
251 }
252 
253 char *av_strdup(const char *s)
254 {
255  char *ptr = NULL;
256  if (s) {
257  size_t len = strlen(s) + 1;
258  ptr = av_realloc(NULL, len);
259  if (ptr)
260  memcpy(ptr, s, len);
261  }
262  return ptr;
263 }
264 
265 char *av_strndup(const char *s, size_t len)
266 {
267  char *ret = NULL, *end;
268 
269  if (!s)
270  return NULL;
271 
272  end = memchr(s, 0, len);
273  if (end)
274  len = end - s;
275 
276  ret = av_realloc(NULL, len + 1);
277  if (!ret)
278  return NULL;
279 
280  memcpy(ret, s, len);
281  ret[len] = 0;
282  return ret;
283 }
284 
285 void *av_memdup(const void *p, size_t size)
286 {
287  void *ptr = NULL;
288  if (p) {
289  ptr = av_malloc(size);
290  if (ptr)
291  memcpy(ptr, p, size);
292  }
293  return ptr;
294 }
295 
296 int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
297 {
298  void **tab;
299  memcpy(&tab, tab_ptr, sizeof(tab));
300 
301  FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
302  tab[*nb_ptr] = elem;
303  memcpy(tab_ptr, &tab, sizeof(tab));
304  }, {
305  return AVERROR(ENOMEM);
306  });
307  return 0;
308 }
309 
310 void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
311 {
312  void **tab;
313  memcpy(&tab, tab_ptr, sizeof(tab));
314 
315  FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
316  tab[*nb_ptr] = elem;
317  memcpy(tab_ptr, &tab, sizeof(tab));
318  }, {
319  *nb_ptr = 0;
320  av_freep(tab_ptr);
321  });
322 }
323 
324 void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
325  const uint8_t *elem_data)
326 {
327  uint8_t *tab_elem_data = NULL;
328 
329  FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {
330  tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
331  if (elem_data)
332  memcpy(tab_elem_data, elem_data, elem_size);
333  else if (CONFIG_MEMORY_POISONING)
334  memset(tab_elem_data, FF_MEMORY_POISON, elem_size);
335  }, {
336  av_freep(tab_ptr);
337  *nb_ptr = 0;
338  });
339  return tab_elem_data;
340 }
341 
342 static void fill16(uint8_t *dst, int len)
343 {
344  uint32_t v = AV_RN16(dst - 2);
345 
346  v |= v << 16;
347 
348  while (len >= 4) {
349  AV_WN32(dst, v);
350  dst += 4;
351  len -= 4;
352  }
353 
354  while (len--) {
355  *dst = dst[-2];
356  dst++;
357  }
358 }
359 
360 static void fill24(uint8_t *dst, int len)
361 {
362 #if HAVE_BIGENDIAN
363  uint32_t v = AV_RB24(dst - 3);
364  uint32_t a = v << 8 | v >> 16;
365  uint32_t b = v << 16 | v >> 8;
366  uint32_t c = v << 24 | v;
367 #else
368  uint32_t v = AV_RL24(dst - 3);
369  uint32_t a = v | v << 24;
370  uint32_t b = v >> 8 | v << 16;
371  uint32_t c = v >> 16 | v << 8;
372 #endif
373 
374  while (len >= 12) {
375  AV_WN32(dst, a);
376  AV_WN32(dst + 4, b);
377  AV_WN32(dst + 8, c);
378  dst += 12;
379  len -= 12;
380  }
381 
382  if (len >= 4) {
383  AV_WN32(dst, a);
384  dst += 4;
385  len -= 4;
386  }
387 
388  if (len >= 4) {
389  AV_WN32(dst, b);
390  dst += 4;
391  len -= 4;
392  }
393 
394  while (len--) {
395  *dst = dst[-3];
396  dst++;
397  }
398 }
399 
400 static void fill32(uint8_t *dst, int len)
401 {
402  uint32_t v = AV_RN32(dst - 4);
403 
404 #if HAVE_FAST_64BIT
405  uint64_t v2= v + ((uint64_t)v<<32);
406  while (len >= 32) {
407  AV_WN64(dst , v2);
408  AV_WN64(dst+ 8, v2);
409  AV_WN64(dst+16, v2);
410  AV_WN64(dst+24, v2);
411  dst += 32;
412  len -= 32;
413  }
414 #endif
415 
416  while (len >= 4) {
417  AV_WN32(dst, v);
418  dst += 4;
419  len -= 4;
420  }
421 
422  while (len--) {
423  *dst = dst[-4];
424  dst++;
425  }
426 }
427 
428 void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
429 {
430  const uint8_t *src = &dst[-back];
431  if (!back)
432  return;
433 
434  if (back == 1) {
435  memset(dst, *src, cnt);
436  } else if (back == 2) {
437  fill16(dst, cnt);
438  } else if (back == 3) {
439  fill24(dst, cnt);
440  } else if (back == 4) {
441  fill32(dst, cnt);
442  } else {
443  if (cnt >= 16) {
444  int blocklen = back;
445  while (cnt > blocklen) {
446  memcpy(dst, src, blocklen);
447  dst += blocklen;
448  cnt -= blocklen;
449  blocklen <<= 1;
450  }
451  memcpy(dst, src, cnt);
452  return;
453  }
454  if (cnt >= 8) {
455  AV_COPY32U(dst, src);
456  AV_COPY32U(dst + 4, src + 4);
457  src += 8;
458  dst += 8;
459  cnt -= 8;
460  }
461  if (cnt >= 4) {
462  AV_COPY32U(dst, src);
463  src += 4;
464  dst += 4;
465  cnt -= 4;
466  }
467  if (cnt >= 2) {
468  AV_COPY16U(dst, src);
469  src += 2;
470  dst += 2;
471  cnt -= 2;
472  }
473  if (cnt)
474  *dst = *src;
475  }
476 }
477 
478 void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
479 {
480  if (min_size <= *size)
481  return ptr;
482 
483  if (min_size > max_alloc_size) {
484  *size = 0;
485  return NULL;
486  }
487 
488  min_size = FFMIN(max_alloc_size, FFMAX(min_size + min_size / 16 + 32, min_size));
489 
490  ptr = av_realloc(ptr, min_size);
491  /* we could set this to the unmodified min_size but this is safer
492  * if the user lost the ptr and uses NULL now
493  */
494  if (!ptr)
495  min_size = 0;
496 
497  *size = min_size;
498 
499  return ptr;
500 }
501 
502 void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
503 {
504  ff_fast_malloc(ptr, size, min_size, 0);
505 }
506 
507 void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
508 {
509  ff_fast_malloc(ptr, size, min_size, 1);
510 }
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
r
const char * r
Definition: vf_curves.c:116
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_RN16
#define AV_RN16(p)
Definition: intreadwrite.h:360
ff_fast_malloc
static int ff_fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc)
Definition: mem_internal.h:139
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:324
b
#define b
Definition: input.c:41
FF_MEMORY_POISON
#define FF_MEMORY_POISON
Definition: internal.h:88
av_mallocz_array
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:190
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:285
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:146
fill16
static void fill16(uint8_t *dst, int len)
Definition: mem.c:342
tab
static const struct twinvq_data tab
Definition: twinvq_data.h:10345
val
static double val(void *priv, double ch)
Definition: aeval.c:76
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:428
av_malloc_array
void * av_malloc_array(size_t nmemb, size_t size)
Definition: mem.c:182
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:478
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)
Definition: mem.c:198
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:228
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:675
limits.h
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:360
result
and forward the result(frame or status change) to the corresponding input. If nothing is possible
NULL
#define NULL
Definition: coverity.c:32
AV_RN32
#define AV_RN32(p)
Definition: intreadwrite.h:364
src
#define src
Definition: vp8dsp.c:255
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:507
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:310
AV_WN32
#define AV_WN32(p, v)
Definition: intreadwrite.h:376
FFMAX
#define FFMAX(a, b)
Definition: common.h:103
size
int size
Definition: twinvq_data.h:10344
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:161
fill32
static void fill32(uint8_t *dst, int len)
Definition: mem.c:400
AV_RL24
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_RL24
Definition: bytestream.h:93
FFMIN
#define FFMIN(a, b)
Definition: common.h:105
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:206
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:134
common.h
uint8_t
uint8_t
Definition: audio_convert.c:194
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:237
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:219
ret
ret
Definition: filter_design.txt:187
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
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:296
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:245
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:253
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:502
AV_WN64
#define AV_WN64(p, v)
Definition: intreadwrite.h:380
AV_RB24
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_RB24
Definition: bytestream.h:97
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:265