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  if (!size || nmemb >= INT_MAX / size)
187  return NULL;
188  return av_malloc(nmemb * size);
189 }
190 
191 void *av_mallocz_array(size_t nmemb, size_t size)
192 {
193  if (!size || nmemb >= INT_MAX / size)
194  return NULL;
195  return av_mallocz(nmemb * size);
196 }
197 
198 void *av_realloc_array(void *ptr, size_t nmemb, size_t size)
199 {
200  if (!size || nmemb >= INT_MAX / size)
201  return NULL;
202  return av_realloc(ptr, nmemb * size);
203 }
204 
205 int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
206 {
207  void *val;
208 
209  memcpy(&val, ptr, sizeof(val));
210  val = av_realloc_f(val, nmemb, size);
211  memcpy(ptr, &val, sizeof(val));
212  if (!val && nmemb && size)
213  return AVERROR(ENOMEM);
214 
215  return 0;
216 }
217 
218 void av_free(void *ptr)
219 {
220 #if HAVE_ALIGNED_MALLOC
221  _aligned_free(ptr);
222 #else
223  free(ptr);
224 #endif
225 }
226 
227 void av_freep(void *arg)
228 {
229  void *val;
230 
231  memcpy(&val, arg, sizeof(val));
232  memcpy(arg, &(void *){ NULL }, sizeof(val));
233  av_free(val);
234 }
235 
236 void *av_mallocz(size_t size)
237 {
238  void *ptr = av_malloc(size);
239  if (ptr)
240  memset(ptr, 0, size);
241  return ptr;
242 }
243 
244 void *av_calloc(size_t nmemb, size_t size)
245 {
246  if (size <= 0 || nmemb >= INT_MAX / size)
247  return NULL;
248  return av_mallocz(nmemb * size);
249 }
250 
251 char *av_strdup(const char *s)
252 {
253  char *ptr = NULL;
254  if (s) {
255  size_t len = strlen(s) + 1;
256  ptr = av_realloc(NULL, len);
257  if (ptr)
258  memcpy(ptr, s, len);
259  }
260  return ptr;
261 }
262 
263 char *av_strndup(const char *s, size_t len)
264 {
265  char *ret = NULL, *end;
266 
267  if (!s)
268  return NULL;
269 
270  end = memchr(s, 0, len);
271  if (end)
272  len = end - s;
273 
274  ret = av_realloc(NULL, len + 1);
275  if (!ret)
276  return NULL;
277 
278  memcpy(ret, s, len);
279  ret[len] = 0;
280  return ret;
281 }
282 
283 void *av_memdup(const void *p, size_t size)
284 {
285  void *ptr = NULL;
286  if (p) {
287  ptr = av_malloc(size);
288  if (ptr)
289  memcpy(ptr, p, size);
290  }
291  return ptr;
292 }
293 
294 int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
295 {
296  void **tab;
297  memcpy(&tab, tab_ptr, sizeof(tab));
298 
299  FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
300  tab[*nb_ptr] = elem;
301  memcpy(tab_ptr, &tab, sizeof(tab));
302  }, {
303  return AVERROR(ENOMEM);
304  });
305  return 0;
306 }
307 
308 void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
309 {
310  void **tab;
311  memcpy(&tab, tab_ptr, sizeof(tab));
312 
313  FF_DYNARRAY_ADD(INT_MAX, sizeof(*tab), tab, *nb_ptr, {
314  tab[*nb_ptr] = elem;
315  memcpy(tab_ptr, &tab, sizeof(tab));
316  }, {
317  *nb_ptr = 0;
318  av_freep(tab_ptr);
319  });
320 }
321 
322 void *av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size,
323  const uint8_t *elem_data)
324 {
325  uint8_t *tab_elem_data = NULL;
326 
327  FF_DYNARRAY_ADD(INT_MAX, elem_size, *tab_ptr, *nb_ptr, {
328  tab_elem_data = (uint8_t *)*tab_ptr + (*nb_ptr) * elem_size;
329  if (elem_data)
330  memcpy(tab_elem_data, elem_data, elem_size);
331  else if (CONFIG_MEMORY_POISONING)
332  memset(tab_elem_data, FF_MEMORY_POISON, elem_size);
333  }, {
334  av_freep(tab_ptr);
335  *nb_ptr = 0;
336  });
337  return tab_elem_data;
338 }
339 
340 static void fill16(uint8_t *dst, int len)
341 {
342  uint32_t v = AV_RN16(dst - 2);
343 
344  v |= v << 16;
345 
346  while (len >= 4) {
347  AV_WN32(dst, v);
348  dst += 4;
349  len -= 4;
350  }
351 
352  while (len--) {
353  *dst = dst[-2];
354  dst++;
355  }
356 }
357 
358 static void fill24(uint8_t *dst, int len)
359 {
360 #if HAVE_BIGENDIAN
361  uint32_t v = AV_RB24(dst - 3);
362  uint32_t a = v << 8 | v >> 16;
363  uint32_t b = v << 16 | v >> 8;
364  uint32_t c = v << 24 | v;
365 #else
366  uint32_t v = AV_RL24(dst - 3);
367  uint32_t a = v | v << 24;
368  uint32_t b = v >> 8 | v << 16;
369  uint32_t c = v >> 16 | v << 8;
370 #endif
371 
372  while (len >= 12) {
373  AV_WN32(dst, a);
374  AV_WN32(dst + 4, b);
375  AV_WN32(dst + 8, c);
376  dst += 12;
377  len -= 12;
378  }
379 
380  if (len >= 4) {
381  AV_WN32(dst, a);
382  dst += 4;
383  len -= 4;
384  }
385 
386  if (len >= 4) {
387  AV_WN32(dst, b);
388  dst += 4;
389  len -= 4;
390  }
391 
392  while (len--) {
393  *dst = dst[-3];
394  dst++;
395  }
396 }
397 
398 static void fill32(uint8_t *dst, int len)
399 {
400  uint32_t v = AV_RN32(dst - 4);
401 
402 #if HAVE_FAST_64BIT
403  uint64_t v2= v + ((uint64_t)v<<32);
404  while (len >= 32) {
405  AV_WN64(dst , v2);
406  AV_WN64(dst+ 8, v2);
407  AV_WN64(dst+16, v2);
408  AV_WN64(dst+24, v2);
409  dst += 32;
410  len -= 32;
411  }
412 #endif
413 
414  while (len >= 4) {
415  AV_WN32(dst, v);
416  dst += 4;
417  len -= 4;
418  }
419 
420  while (len--) {
421  *dst = dst[-4];
422  dst++;
423  }
424 }
425 
426 void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
427 {
428  const uint8_t *src = &dst[-back];
429  if (!back)
430  return;
431 
432  if (back == 1) {
433  memset(dst, *src, cnt);
434  } else if (back == 2) {
435  fill16(dst, cnt);
436  } else if (back == 3) {
437  fill24(dst, cnt);
438  } else if (back == 4) {
439  fill32(dst, cnt);
440  } else {
441  if (cnt >= 16) {
442  int blocklen = back;
443  while (cnt > blocklen) {
444  memcpy(dst, src, blocklen);
445  dst += blocklen;
446  cnt -= blocklen;
447  blocklen <<= 1;
448  }
449  memcpy(dst, src, cnt);
450  return;
451  }
452  if (cnt >= 8) {
453  AV_COPY32U(dst, src);
454  AV_COPY32U(dst + 4, src + 4);
455  src += 8;
456  dst += 8;
457  cnt -= 8;
458  }
459  if (cnt >= 4) {
460  AV_COPY32U(dst, src);
461  src += 4;
462  dst += 4;
463  cnt -= 4;
464  }
465  if (cnt >= 2) {
466  AV_COPY16U(dst, src);
467  src += 2;
468  dst += 2;
469  cnt -= 2;
470  }
471  if (cnt)
472  *dst = *src;
473  }
474 }
475 
476 void *av_fast_realloc(void *ptr, unsigned int *size, size_t min_size)
477 {
478  if (min_size <= *size)
479  return ptr;
480 
481  if (min_size > max_alloc_size - 32) {
482  *size = 0;
483  return NULL;
484  }
485 
486  min_size = FFMIN(max_alloc_size - 32, FFMAX(min_size + min_size / 16 + 32, min_size));
487 
488  ptr = av_realloc(ptr, min_size);
489  /* we could set this to the unmodified min_size but this is safer
490  * if the user lost the ptr and uses NULL now
491  */
492  if (!ptr)
493  min_size = 0;
494 
495  *size = min_size;
496 
497  return ptr;
498 }
499 
500 void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
501 {
502  ff_fast_malloc(ptr, size, min_size, 0);
503 }
504 
505 void av_fast_mallocz(void *ptr, unsigned int *size, size_t min_size)
506 {
507  ff_fast_malloc(ptr, size, min_size, 1);
508 }
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:114
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
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:322
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)
Definition: mem.c:191
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:283
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:340
tab
static const struct twinvq_data tab
Definition: twinvq_data.h:11135
src
#define src
Definition: vp8dsp.c:254
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:426
av_malloc_array
void * av_malloc_array(size_t nmemb, size_t size)
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:476
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:227
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
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:358
NULL
#define NULL
Definition: coverity.c:32
AV_RN32
#define AV_RN32(p)
Definition: intreadwrite.h:364
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:505
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:308
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:398
AV_RL24
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_RL24
Definition: bytestream.h:89
val
const char const char void * val
Definition: avisynth_c.h:863
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:205
av_realloc
void * av_realloc(void *ptr, size_t size)
Allocate, reallocate, or free a block of memory.
Definition: mem.c:135
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:236
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:218
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
align
const AVS_VideoInfo int align
Definition: avisynth_c.h:887
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:294
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
config.h
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
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:500
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:93
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263