E_OUTOFMEMORY
最近在维护一个以Directshow框架构建的一个摄像头程序时,发现当摄像头分辨率超过1920*1080后,在YUY2 Format会随着分辨率的提高更频繁出现E_OUTOFMEMORY,而不能Preview的情况,摄像头还支持MJPG,不过还行在MJPG好像没有这个问题。
分辨率定义如下
#define DF_IMG_SIZE_3M 20481536
#define DF_IMG_SIZE_5M 25601920
#define DF_IMG_SIZE_12M 40963072
#define DF_IMG_SIZE_16M 46724096
#define DF_MAX_IMG_SIZE DF_IMG_SIZE_16M
经Debug发现,程序中使用new 操作符在堆区动态申请了很多的Heap Memory,同时有很多类对象也是动态new的。
例如其中几个大的Buffer 定义如下:
BYTE pYUY2 = new BYTE[sizeof(BYTE)DF_MAX_IMG_SIZE2];*
BYTE pBGRBuffer = new BYTE[sizeof(BYTE)DF_MAX_IMG_SIZE3];*
BYTE pBGRTempBuffer = new BYTE[sizeof(BYTE)DF_MAX_IMG_SIZE3];*
…
还有很多个这样的大的Buffer,这边就不过多说明了。。。
由于不是计算机专业出身,最开始没有想到问题所在,以为所能申请的内存大小与物理内存是有关的,物理内存越大,所能申请的堆区内存应该就越大。后来在看了几篇与 new 相关的文章之后,发现每个程序运行的时候Windows操作系统会为这个进程分配4G的虚拟内存,包括全局变量区、栈区、堆区…这边我也不是很熟悉,现在主要关注堆区也就没有深入了解太多。发现其实每个进程所能动态申请的堆区大小不超过4G,这里我就有点疑问了,总共才4G,堆区居然就可以最大申请4G,不过也没有深究。
不过大概算了下,在程序中所申请的堆区大小基本上可能已经超过1G,而我的程序是在做了1+ 次切换Capture Pin Property 的分辨率后才会出现E_OUTOFMEMORY的情况。
基于此对Project Properties做了改动,Linker --> System --> Enable Larger Address: Support Address Larger than 2 Gigabytes后再对程序做了测试,发现需要多做几次 分辨率切换才会出现 E_OUTOFMEMORY的情况。
在此基础上又去对Source code 做了Check,尽量确保每个new 的 对象都有在相应的点被delete,不过也有可能不够完善,发现情况仍然存在。所以现在也不太清楚具体是什么地方在耗堆区内存资源,还是说Directshow本身在画面Preview时,内部也在耗堆区内存,就不得而知了。还得再花点时间去看看相关资料咯…
如有大佬知晓其中缘由,还请指教,小弟感激不尽!^ _ ^