解决LoadImage加载图片报告内存不足的错误

11 篇文章 0 订阅
10 篇文章 0 订阅

在使用Win32 API LoadImage加载大量图片,或者加载很大的图片的时候,你可能会碰到图片加载失败,而且调用GetLastError显示错误是“内存不足,无法完成此操作!”,打开任务管理器,却发现系统里面还有大量的内存空闲。比如使用下面的代码你就会碰到这个错误当然你要准备大量的BMP图片:

#include "StdAfx.h"

#include "SampleBase.h"

#include <windows.h>

#include <shlwapi.h>

#include <stack>

#include <string>

 

#ifdef UNICODE

#  define tstring wstring

#else

#  define tstring string

#endif

 

using namespace std;

 

void CLoadImageIssueSample::Run(HWND hwnd)

{

    WIN32_FIND_DATA findFileData;

    ZeroMemory(&findFileData, sizeof(WIN32_FIND_DATA));

    TCHAR szCurDir[MAX_PATH];

 

    ::GetCurrentDirectory(MAX_PATH, szCurDir);

 

    HANDLE handle = FindFirstFile(TEXT("Resources//CLoadImageIssueSample//*"), &findFileData);

    stack<tstring> dirStack;

    tstring baseDir(szCurDir);

    baseDir += TEXT("//");

    baseDir += TEXT("Resources//CLoadImageIssueSample");

    while ( handle != INVALID_HANDLE_VALUE )

    {

        do

        {

            tstring fileName(baseDir);

            fileName += TEXT("//");

            fileName += findFileData.cFileName;

 

            if ( (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ==

                 FILE_ATTRIBUTE_DIRECTORY )

            {

                if ( StrCmp(findFileData.cFileName, TEXT(".")) == 0 ||

                     StrCmp(findFileData.cFileName, TEXT("..")) == 0 )

                     continue;

                else

                {

                    dirStack.push(fileName);

                    // 并不删除cFileName,到时一起释放

                    ZeroMemory(&findFileData, sizeof(WIN32_FIND_DATA));

                }

            }

            else

            {

                if ( NULL == ::LoadImage(NULL, fileName.c_str(),

                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE) )

                {   

                    LPVOID lpMsgBuf;

                    DWORD dw = GetLastError();

 

                    FormatMessage(

                        FORMAT_MESSAGE_ALLOCATE_BUFFER |

                        FORMAT_MESSAGE_FROM_SYSTEM |

                        FORMAT_MESSAGE_IGNORE_INSERTS,

                        NULL,

                        dw,

                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

                        (LPTSTR) &lpMsgBuf,

                        0, NULL );

 

                    MessageBox(NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK);

                    LocalFree(lpMsgBuf);

                }

 

                ZeroMemory(&findFileData, sizeof(WIN32_FIND_DATA));

            }

        } while ( FindNextFile(handle, &findFileData) != 0 );

 

        FindClose(handle);

        if ( !dirStack.empty() )

        {

            baseDir = dirStack.top();

            tstring format = baseDir + TEXT("//*");

            handle = FindFirstFile(format.c_str(), &findFileData);

            dirStack.pop();

        }

    }

}

 

这个错误是因为使用LoadImage加载图片资源时,LoadImage默认创建的是DDB格式的图像,而DDB图像是分配在Desktop Heap上面的,在Windows XPWindows 2003里,这个Desktop Heap是被其他很多运行在同一个Windows会话(Session)里面的程序公用的,这个Heap的大小默认只有20M。虽然你可以在注册表里面更改成更大的值,但是在32Windows上面Session View Space的大小有限,而Desktop HeapSession View Space的一部分,这就意味着如果你将Desktop Heap的值改得很大,会影响在Session View Space里面其他资源的内存分配。

 

解决方案有两个:

1.         使用64位的Windows,或者升级到Vista

2.         或者修改代码,让LoadImageDIB格式加载图片资源,这样你的图像资源就不是分配在Desktop Heap上面了,也就跳过了20M内存的限制。也就是说你将代码改成下面这样子就可以了:

if ( NULL == ::LoadImage(NULL, fileName.c_str(),

                                         IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION) )

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值