1
#if AV_GCC_VERSION_AT_LEAST(4,3)
#define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__)))
#else
#define av_alloc_size(...)
#endif

/**
* Allocate a memory block for an array with av_mallocz().
*
* The allocated memory will have size `size * nmemb` bytes.
*
* @param nmemb Number of elements
* @param size  Size of the single element
* @return Pointer to the allocated block, or `NULL` if the block cannot
*         be allocated
*
* @see av_mallocz()
* @see av_malloc_array()
*/

av_alloc_size(1, 2) static inline void *av_mallocz_array(size_t nmemb, 
size_t size)
{
   if (!size || nmemb >= INT_MAX / size)
      return NULL;
   return av_mallocz(nmemb * size);
}

I am a c lang primer. I see this function when I read open source. but what kind of function is it? I have never seen this kind of function before. av_alloc_size(1, 2) and *av_mallocz_array have any relationship?

Satsrag
  • 33
  • 7
  • 1
    `av_alloc_size` is a *preprocessor macro*. [A good beginners book](http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list) should talk about them. And if you're a beginner then the code you're looking at might be a bit to advanced for you. Code in projects like e.g. ffmpeg are *not* for beginners. – Some programmer dude Jul 03 '17 at 06:59
  • thanks your explanation – Satsrag Jul 03 '17 at 10:01

1 Answers1

3

It's just a macro that expands to a GCC-specific attribute (__attribute__((alloc_size()))) that further "describes" the function. From the GCC documentation:

alloc_size

The alloc_size attribute is used to tell the compiler that the function return value points to memory, where the size is given by one or two of the functions parameters. GCC uses this information to improve the correctness of __builtin_object_size.

The function parameter(s) denoting the allocated size are specified by one or two integer arguments supplied to the attribute. The allocated size is either the value of the single function argument specified or the product of the two function arguments specified. Argument numbering starts at one.

For instance,

void* my_calloc(size_t, size_t) __attribute__((alloc_size(1,2)))
void* my_realloc(void*, size_t) __attribute__((alloc_size(2)))

declares that my_calloc returns memory of the size given by the product of parameter 1 and 2 and that my_realloc returns memory of the size given by parameter 2.

So, in short, it helps the compiler better "understand" the code by letting it know that the function performs a dynamic memory allocation, like the standard functions malloc() and calloc(). The code would of course work without that as well.

These lines:

#if AV_GCC_VERSION_AT_LEAST(4,3)
#define av_alloc_size(...) __attribute__((alloc_size(__VA_ARGS__)))
#else
#define av_alloc_size(...)
#endif

make sure the expansion only happens when compiling with GCC version 4.3 or later. In all other cases, the second #define just makes av_alloc_size() expand to nothing at all (empty string).

  • Thanks. According to your explanation and some docs from net, There are two points that I did not know before: macro and void * .---------- macro->Simple to understand copy. void * -> Return a pointer to any value. so after preprocessor : static inline void *av_mallocz_array(size_t nmemb, size_t size) __attribute__((alloc_size(1,2))) or static inline void *av_mallocz_array(size_t nmemb, size_t size) – Satsrag Jul 03 '17 at 09:56