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  /* 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 }
#define NULL
Definition: coverity.c:32
void * av_realloc_f(void *ptr, size_t nelem, size_t elsize)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:148
void av_max_alloc(size_t max)
Set the maximum size that may be allocated in one block.
Definition: mem.c:73
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
Memory handling functions.
#define FF_MEMORY_POISON
Definition: internal.h:89
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:36
Convenience header that includes libavutil&#39;s core.
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
static void fill16(uint8_t *dst, int len)
Definition: mem.c:344
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:247
uint8_t
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
static void fill32(uint8_t *dst, int len)
Definition: mem.c:402
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
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:430
#define max(a, b)
Definition: cuda_runtime.h:33
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
Definition: mem.c:298
ptrdiff_t size
Definition: opengl_enc.c:100
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:200
#define src
Definition: vp8dsp.c:254
#define AV_COPY16U(d, s)
Definition: intreadwrite.h:568
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
const char * r
Definition: vf_curves.c:114
const char * arg
Definition: jacosubdec.c:66
simple assert() macros that are a bit more flexible than ISO C assert().
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_RL24
Definition: bytestream.h:87
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition: mem.c:287
#define FFMAX(a, b)
Definition: common.h:94
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
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
#define b
Definition: input.c:41
void * av_malloc_array(size_t nmemb, size_t size)
Definition: mem.c:184
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
#define FFMIN(a, b)
Definition: common.h:96
#define AV_COPY32U(d, s)
Definition: intreadwrite.h:572
#define s(width, name)
Definition: cbs_vp9.c:257
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
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
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:255
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:87
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
#define AV_RN16(p)
Definition: intreadwrite.h:360
#define ALIGN
Definition: mem.c:64
static size_t max_alloc_size
Definition: mem.c:71
#define AV_RN32(p)
Definition: intreadwrite.h:364
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
static void fill24(uint8_t *dst, int len)
Definition: mem.c:362
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
#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
common internal and external API header
#define AV_WN32(p, v)
Definition: intreadwrite.h:376
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
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
int len
static const struct twinvq_data tab
and forward the result(frame or status change) to the corresponding input.If nothing is possible
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
static double val(void *priv, double ch)
Definition: aeval.c:76
static int ff_fast_malloc(void *ptr, unsigned int *size, size_t min_size, int zero_realloc)
Definition: mem_internal.h:27
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:267
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:192
#define AV_WN64(p, v)
Definition: intreadwrite.h:380