FFMPEG4.1源码分析之 内存管理APIs av_malloc() && av_mallocz()

1  av_malloc() 


av_malloc() 声明:

  • 所属库:libavutil,该库是ffmpeg的功能库,提供了线程,内存,文件,加密等功能
  • 头文件:libavutil/mem.h
  • 该函数作用在于给对象分配内存块,并且是内存对齐的
  • 该函数由两个宏av_malloc_attrib  && av_alloc_size(1)指定了一些编译器属性,作用如后面所描述,更详细的描述见 FFMPEG4.1源码分析之 内存分配
/**
 * Allocate a memory block with alignment suitable for all memory accesses
 * (including vectors if available on the CPU).
 *
 * @param size Size in bytes for the memory block to be allocated
 * @return Pointer to the allocated block, or `NULL` if the block cannot
 *         be allocated
 * @see av_mallocz()
 */
void *av_malloc(size_t size) av_malloc_attrib av_alloc_size(1);
  1. av_malloc_attrib是一个宏定义,如果是在编译器GCC3.1及以上版本的情况下,给方法av_malloc增加属性 __attribute__((__malloc__)),该属性指示编译器按照malloc函数来对待本函数,并且可以对其实施相应的优化措施。后续在研究ffmpeg中内存分配与管理的源码之后,会再尝试写一篇文章详细介绍。此时,先给出几个网上关于该属性的描述相关网址:http://www.keil.com/support/man/docs/armcc/armcc_chr1359124975555.htm;  https://stackoverflow.com/questions/18485447/gcc-attribute-malloc;  https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007bmalloc_007d-function-attribute-3251
    /**
     * @def av_malloc_attrib
     * Function attribute denoting a malloc-like function.
     *
     * @see <a href="https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007bmalloc_007d-function-attribute-3251">Function attribute `malloc` in GCC's documentation</a>
     */
    
    #if AV_GCC_VERSION_AT_LEAST(3,1)
        #define av_malloc_attrib __attribute__((__malloc__))
    #else
        #define av_malloc_attrib
    #endif
  2. av_alloc_size(1)也是一个宏定义,如果是在编译器GCC4.3及以上版本的情况下,给方法增加一个属性__attribute__((alloc_size(1))),告知编译器av_malloc(size_t size)方法的第一个参数,也即size是要分配的空间大小,关于__attribute__((alloc_size(__VA_ARGS__)))属性的详细描述可以见:https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-g_t_0040code_007balloc_005fsize_007d-function-attribute-3220

 av_malloc() 源码:

void *av_malloc(size_t size)
{
    void *ptr = NULL;

    /* let's disallow possibly ambiguous cases */
    if (size > (max_alloc_size - 32))
        return NULL;

#if HAVE_POSIX_MEMALIGN
    if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
    if (posix_memalign(&ptr, ALIGN, size))
        ptr = NULL;
#elif HAVE_ALIGNED_MALLOC
    ptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__
    ptr = memalign(ALIGN, size);
#else
    ptr = memalign(size, ALIGN);
#endif
    /* Why 64?
     * Indeed, we should align it:
     *   on  4 for 386
     *   on 16 for 486
     *   on 32 for 586, PPro - K6-III
     *   on 64 for K7 (maybe for P3 too).
     * Because L1 and L2 caches are aligned on those values.
     * But I don't want to code such logic here!
     */
    /* Why 32?
     * For AVX ASM. SSE / NEON needs only 16.
     * Why not larger? Because I did not see a difference in benchmarks ...
     */
    /* benchmarks with P3
     * memalign(64) + 1          3071, 3051, 3032
     * memalign(64) + 2          3051, 3032, 3041
     * memalign(64) + 4          2911, 2896, 2915
     * memalign(64) + 8          2545, 2554, 2550
     * memalign(64) + 16         2543, 2572, 2563
     * memalign(64) + 32         2546, 2545, 2571
     * memalign(64) + 64         2570, 2533, 2558
     *
     * BTW, malloc seems to do 8-byte alignment by default here.
     */
#else
    ptr = malloc(size);
#endif
    if(!ptr && !size) {           // 在size为0时,将分配一个字节的空间
        size = 1;
        ptr= av_malloc(1);
    }
#if CONFIG_MEMORY_POISONING
    if (ptr)
        memset(ptr, FF_MEMORY_POISON, size);
#endif
    return ptr;
}
  1. 该函数在不同的宏作用下使用了不同的内存分配函数,优先级为posix_memalign() ->_aligned_malloc() -> memalign() -> malloc()。这些宏定义在文件config.h中,这个文件不属于ffpmeg的任何库,这个是ffmpeg源码编译时,configure命令生成的配置文件,在不同的环境下,config.h文件中的宏定义值是不一样的。
  2. 就我当前的编译环境Windows系统,VisualStudio2013update5来说,这几个宏定义分别为如下源代码所示,因此将会使用_aligned_malloc()方法进行内存分配,而该方法定义在如下平台相关的文件中,见下图,另外该方法的详细描述见:MicroSoft Docs:_aligned_malloc
    #define HAVE_POSIX_MEMALIGN 0
    #define HAVE_ALIGNED_MALLOC 1
    #define HAVE_MEMALIGN 0
    __DJGPP__ 未定义
  3. 内存对齐:上述几个函数除了malloc外都具有内存对齐功能,另外还有一个宏ALIGN ,其根据另外两个宏HAVE_AVX512 和HAVE_AVX来决定是按多少位对齐,而HAVE_AVX和HAVE_AVX512指示环境中是否可以使用AVX CPU指令集和AVX512 CPU扩展指令集,能使用更高级的指令集意味着可以使用的寄存器大小会变大,因此对齐的数据位数也会变大。关于AVX与AVX512的详细描述见wikipedia:AVX指令集AVX512

    #define ALIGN (HAVE_AVX512 ? 64 : (HAVE_AVX ? 32 : 16))
  4. 注意到当size=0时,将分配一个字节的空间,这儿是令我奇怪的一点,为什么此处不直接返回NULL就行了?突然又想到在C/C++的空结构体/空类都会占据一个字节以作占位符,见如下示例代码以及结果展示。猜测这儿应该也是起同样的作用。

    #include <stdio.h>
    
    struct EmptyStruct{};
    class EmptyClass{};
    
    int main(int argc, char* argv[]) 
    {
        printf("EmptyStruct'size is %d\n", sizeof(EmptyStruct));
        printf("EmptyClass'size is %d\n", sizeof(EmptyClass));
        getchar();
        return 0;
    }

  5. 最后,宏CONFIG_MEMORY_POISONING决定了分配后的数据是否需要使用数据填充,根据该宏的名称也知道是“毒化,中毒”的意思,通常我们分配内存后一般都是使用0去初始化这块儿内存,但是ffmpeg中如果配置了上述宏定义,那么会使用FF_MEMORY_POISON指定的0x2a去填充分配空间的每个字节。当然,就我目前的环境而言,config.h文件中的 CONFIG_MEMORY_POISONING 被定义为0,也即不进行内存“毒化”。

    #define CONFIG_MEMORY_POISONING 0
    #define FF_MEMORY_POISON 0x2a

2 av_mallocz()


av_mallocz() 声明:

void *av_mallocz(size_t size) av_malloc_attrib av_alloc_size(1);

av_mallocz()  源码: 

void *av_mallocz(size_t size)
{
    void *ptr = av_malloc(size); 使用av_malloc分配内存
    if (ptr)
        memset(ptr, 0, size);    将分配的内存块所有字节置0
    return ptr;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值