VC++“内存资源不足,无法完成此操作”——解决的心路历程(User对象)

30 篇文章 3 订阅

        在上周客户反馈了一个问题,大概意思是在他windows上安装的识别软件中,识别一百多张内容比较复杂的图片时,出现了“刚开始识别的没问题,但是识别到100来张时发现之后的图片都不识别了,没有识别结果”。

        接收到问题立马就着手调试、重现,因为这是很早之前的代码了,由于不熟的缘故刚开始浪费了比较多的时间在搭建环境上(VS2015),不过还好,这个代码一测就测出了问题,还真有这BUG。下面是调试这个bug的详细步骤。

        调试发现我的电脑上用客户的图片测试,虽然中间也走了一些弯路,费了一些功夫,不过最后发现会经常在识别到80张左右的时候跳过识别步骤,自然将问题定位到了识别的模块中。步进调试,继续将问题定位在识别之前的一个读取XML文件的步骤中,定位的问题代码如下:

MSXML2::IXMLDOMDocumentPtr   XmlPtr = NULL;
hr = XmlPtr.CreateInstance(_T("Msxml2.DOMDocument.4.0"));
hr = XmlPtr->load(_variant_t(strOCRName));

最后的那句代码返回值有问题,后续代码抛异常,这是当时发现的直接原因。

        发现这个问题后,经网上查找官方文档,使用相关方法(具体查找xml执行错误的方法见我的另一篇博客地址:MSXML错误输出)分析了XML加载文件错误码和错误的原因,得到“0x8007000e,内存资源不足,无法完成此操作”,也就是系统的分配内存资源不足以支持当前程序在做一些消耗内存资源的操作了。于是临时想了几种解决方案:1.查找是不是有内存没有释放掉,定位问题所在;2.有没有可能在抛异常时,清理掉无用的内存占用,或者采用一种内存更优化的机制;3.会不会跟32位程序有关,寻址有限?;4.增加可用内存(如使能项目属性中的最大内存值>2G(设置方法:VS2015 win32程序使用大内存 (>2GB)设置),增加系统虚拟内存等);

        经过尝试和权衡,最终还是没有用后三种(竟然还研究了半天C++内存池,有一篇资料讲的很不错:https://www.ibm.com/developerworks/cn/linux/l-cn-ppp/index6.html),因为毕竟治标不治本,而且客户当前也不是很捉急。

        经过各种查找资料、各种咨询,也没解决。当时想着用MessageBox弹出错误的原因和错误码,在虚拟机上试试。这一试就尴尬了,虚拟机上竟然没问题?(我的电脑是系统WIN10-内存8G-硬盘1T,虚拟机系统WIN7-内存1G-硬盘40G)

       奇了怪了,再次在物理机上调试,正常出错,但是竟然不弹出提示框。GetlastError呗,(GetLastError返回值及其含义)返回值:1158,表示当前程序已使用了 Window 管理器对象的系统允许的所有句柄。这表明什么?这说明系统给这个应用分配的句柄资源被消耗完了,查资料(相关资料见地址:windows资源管理(内核对象/GDI对象/user对象))发现windows编程中有三种对象是windows系统资源管理的,内核对象、GDI对象、User对象,其中GDI对象和User对象是有数量限制的(最高10000)。知道了这个,赶紧就打开任务管理器,查看我程序发生异常时,GDI对象和User对象有没有明显增长。

       令人惊喜,找到问题所在了,如下图。

       User对象涨到了10000封顶,步进调试发现在某一步骤中识别一次对象数量就增加120多,怪不得提示内存资源不足呢。接下来就查查这User对象有哪些方法,是不是有啥创建的没销毁的,查找官方文档:User对象​​​​​​​ 。

       官方文档介绍的很清晰,有对应的创建方法就必须要对应的销毁掉。继续debug呗,皇天不负有心人,这代码架构很好,当时是真不好找啊,有问题的部分代码如下:

 

       定睛一看,还真没有用销毁的方法,修改:在hwnd生命周期结束时,调用DestroyWindow(hwnd)销毁掉即可。

       编译运行,试上他200张,自然结果完美运行不出错。

 

       这次经历很有启发,还是要多看官方文档,而且找BUG千万不能放过任何一个小问题,只要有一点不对劲的就要抓住(因为在调用xml的load方法时,资料上说返回值是0是正确值,然而我试了数十次结果都是-1才是正确的返回,0才是错误的返回),还要多问,刚接手的代码就得多问,不能一个人钻。

      但是还有一点不理解:为什么win7上测试程序,user对象超出10000限制了,还是能正常识别呢?希望有了解的大佬们不吝赐教!

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值