参考链接

  • FFmpeg源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)_雷霄骅的博客-CSDN博客_av_malloc

内容介绍

  • 内存操作的常见函数位于libavutil\mem.c中
  • 本文记录最常使用的几个函数:
    • av_malloc()
    • av_realloc()
    • av_mallocz()
    • av_calloc()
    • av_free()
    • av_freep()

代码

av_malloc()

void *av_malloc(size_t size)
{void *ptr = NULL;if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))return NULL;#if HAVE_POSIX_MEMALIGNif (size) //OS X on SDK 10.6 has a broken posix_memalign implementationif (posix_memalign(&ptr, ALIGN, size))ptr = NULL;
#elif HAVE_ALIGNED_MALLOCptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__ptr = memalign(ALIGN, size);
#elseptr = 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.*/
#elseptr = malloc(size);
#endifif(!ptr && !size) {size = 1;ptr= av_malloc(1);}
#if CONFIG_MEMORY_POISONINGif (ptr)memset(ptr, FF_MEMORY_POISON, size);
#endifreturn ptr;
}
  • 如果不考虑上述代码中的一大堆宏定义
  • av_malloc()的代码可以简化成如下形式
  • 可以看出,此时的av_malloc()就是简单的封装了系统函数malloc(),并做了一些错误检查工作
void *av_malloc(size_t size)
{void *ptr = NULL;/* let's disallow possibly ambiguous cases */if (size > (max_alloc_size - 32))return NULL;ptr = malloc(size);if(!ptr && !size) {size = 1;ptr= av_malloc(1);}return ptr;
}

av_realloc()

void *av_realloc(void *ptr, size_t size)
{void *ret;if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))return NULL;#if HAVE_ALIGNED_MALLOCret = _aligned_realloc(ptr, size + !size, ALIGN);
#elseret = realloc(ptr, size + !size);
#endif
#if CONFIG_MEMORY_POISONINGif (ret && !ptr)memset(ret, FF_MEMORY_POISON, size);
#endifreturn ret;
}
  • 默认情况下的代码:
  • 可以看出av_realloc()简单封装了系统的realloc()函数。
  • C 库函数 – realloc() | 菜鸟教程
void *av_realloc(void *ptr, size_t size)
{/* let's disallow possibly ambiguous cases */if (size > (max_alloc_size - 32))return NULL;return realloc(ptr, size + !size);
}

av_mallocz()

void *av_mallocz(size_t size)
{void *ptr = av_malloc(size);if (ptr)memset(ptr, 0, size);return ptr;
}
  • av_mallocz()可以理解为av_malloc()+zeromemory
  • av_mallocz()中调用了av_malloc()之后,又调用memset()将分配的内存设置为0

av_calloc()

void *av_calloc(size_t nmemb, size_t size)
{size_t result;if (size_mult(nmemb, size, &result) < 0)return NULL;return av_mallocz(result);
}
static int size_mult(size_t a, size_t b, size_t *r)
{size_t t;#if (!defined(__INTEL_COMPILER) && AV_GCC_VERSION_AT_LEAST(5,1)) || AV_HAS_BUILTIN(__builtin_mul_overflow)if (__builtin_mul_overflow(a, b, &t))return AVERROR(EINVAL);
#elset = a * b;/* Hack inspired from glibc: don't try the division if nelem and elsize* are both less than sqrt(SIZE_MAX). */if ((a | b) >= ((size_t)1 << (sizeof(size_t) * 4)) && a && t / a != b)return AVERROR(EINVAL);
#endif*r = t;return 0;
}
  • av_calloc()则是简单封装了av_mallocz()
  • 从代码中可以看出,它调用av_mallocz()分配了nmemb*size个字节的内存。

av_free()

void av_free(void *ptr)
{
#if HAVE_ALIGNED_MALLOC_aligned_free(ptr);
#elsefree(ptr);
#endif
}
  • 可以看出av_free()简单的封装了free()

av_freep()

void av_freep(void *arg)
{void *val;memcpy(&val, arg, sizeof(val));memcpy(arg, &(void *){ NULL }, sizeof(val));av_free(val);
}
  • av_freep()简单封装了av_free()。并且在释放内存之后将目标指针设置为NULL。
  • C 库函数 – memcpy() | 菜鸟教程

补充知识

内存对齐

  • 参考链接:计算机中的内存对齐与大小端 | MuYi's Blog
  • 程序员通常认为内存就是一个字节数组,每次可以一个一个字节存取内存。例如在C语言中使用char *指代“一块内存”,Java中使用byte[]指代一块内存。如下所示。

  • 但那实际上计算机处理器却不是这样认为的。处理器相对比较“懒惰”,它以块为单位进行数据的读取,块的大小可以是2字节,4字节,8字节,16字节甚至32字节来存取内存。例如下图显示了以4字节为单位读写内存的处理器“看待”上述内存的方式。

  • 上述的存取单位的大小称之为内存存取粒度。
  • 下面看一个实例,分别从地址0,和地址1读取4个字节到寄存器。
  • 从程序员的角度来看,读取方式如下图所示。

  • 而2字节存取粒度的处理器的读取方式如下图所示。

  • 可以看出2字节存取粒度的处理器从地址0读取4个字节一共读取2次;从地址1读取4个字节一共读取了3次。
  • 存储的时候也是将2个字节作为数据块的大小进行存储
  • 由于每次读取的开销是固定的,因此从地址1读取4字节的效率有所下降。
  • 4字节存取粒度的处理器的读取方式如下图所示。

  • 可以看出4字节存取粒度的处理器从地址0读取4个字节一共读取1次;从地址1读取4个字节一共读取了2次。从地址1读取的开销比从地址0读取多了一倍。
  • 由此可见内存不对齐对CPU的性能是有影响的。

FFmpeg源代码简单分析-通用- 内存的分配和释放(av_malloc()、av_free()等)相关推荐

  1. FFmpeg源代码简单分析:内存的分配和释放(av_malloc()、av_free()等)

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  2. ffmpeg源代码处理流程分析_FFmpeg源代码简单分析:内存的分配和释放

    内存操作的常见函数位于libavutil\mem.c中.本文记录FFmpeg开发中最常使用的几个函数:av_malloc(),av_realloc(),av_mallocz(),av_calloc() ...

  3. FFmpeg源代码简单分析-通用-avio_open2()

    参考链接 FFmpeg源代码简单分析:avio_open2()_雷霄骅的博客-CSDN博客_avio_open avio_open2() 该函数用于打开FFmpeg的输入输出文件 avio_open2 ...

  4. FFmpeg源代码简单分析-通用-avcodec_open2()

    参考链接 FFmpeg源代码简单分析:avcodec_open2()_雷霄骅的博客-CSDN博客 avcodec_open2() 该函数用于初始化一个音视频编解码器的AVCodecContext av ...

  5. FFmpeg源代码简单分析:libavdevice的gdigrab

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  6. FFmpeg源代码简单分析:libavdevice的avdevice_register_all()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  7. FFmpeg源代码简单分析:configure

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  8. FFmpeg源代码简单分析:makefile

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  9. FFmpeg源代码简单分析:libswscale的sws_getContext()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

最新文章

  1. java NIO详解
  2. 1.为什么使用spring boot
  3. MFC C++ 获取外网IP地址
  4. 微软为什么要“杀死”小娜?
  5. boost::mp11::mp_remove相关用法的测试程序
  6. OSI模型和TCP/IP协议族
  7. 偏函数 匿名函数 高阶函数 map filter reduce
  8. php替代eval_PHP:需要eval()的替代方法来动态构建多维数组
  9. 接口测试--apipost变量使用(一)
  10. 中国三级流域空间分布数据/国家新区分布数据/NPP净初级生产力数据/植被覆盖空间分布数据/土地利用数据/NDVI数据/植被类型分布/土壤类型数据
  11. 利用rsyslog 对Linux用户进行审计
  12. 微信应用开发简单示例,学生自助报道系统
  13. 基于Web的教学网站前端开发设计 报告+任务书+html源码
  14. 记一次查询性能优化,原30s+,现0.5s~20s
  15. 打开小米5开发者选项
  16. win10自带邮箱客户端登录163邮箱:无法访问该账户,需要更新密码或授权码
  17. element-ui 回到顶部组件el-backtop
  18. 在 linux 中管理罗技优联接收器
  19. 2022年南京Java培训机构排名,实力突出遥遥领先
  20. [1150]Linux服务器上使用rz命令上传文件报:Segmentation Fault

热门文章

  1. DBShop后台RCE之曲线救国
  2. 在家打LOL的ping很高老是掉线怎么办?(亲测有一定效果)PC打游戏延迟很高怎么办?(有通用性)
  3. QTA自动化测试框架(二)
  4. 易语言excel表读写操作
  5. 谷歌浏览器导出书签、导入书签,html 格式 。QQ浏览器导出书签、导入书签,html 格式
  6. if 和 switch 语句
  7. 成为 Google 认证机器学习工程师,零基础也只需要 2 步!
  8. canvas文字粒子特效
  9. TI DSP TMS320C66x学习笔记之DSP优化经验
  10. 《大话传输网》学习笔记(一)——————模拟通讯、数字通讯、业务网、GSM移动网、PCM脉冲编码调制(E1)、传送网、PDH和SDH