很奇怪的内存消耗

时间:2022-02-13 17:24:32
    大家好!在下最近做了一个图像处理的MFC应用程序,当执行检索功能时,发现内存消耗很厉害(100多兆)。当把程序窗口最小化以后可以看到任务管理器中进程内存消耗恢复到正常水平,但是再看系统内存消耗仍然是100多兆。在下感到十分困惑,后来又发现了一个症状:当不停地加载图片时,内存消耗逐渐增加。我又打开ACDSee软件不停地加载图片发现其始终维持在10MB左右,而我的程序每次都增加几十KB。我在网上搜了一些关于内存泄露的讨论,但是我开辟的空间都释放了呀,恳请高手指点!代码稍后贴上

22 个解决方案

#1


你释放是最后关闭的时候释放还是运行过程中,不用就释放?
还有,你运行过程中申请的内存多么?

#2


可以使用内存池等防止反复申请释放内存》。。

#3


肯定是某些资源你没有及时释放造成的。还是再仔细检查一下吧。不妨把你用到的资源都是如何处理的描述一下。
特别是你加载图片的代码,不妨拿出来。

#4


把代码贴出来看看

#5


而我的程序每次都增加几十KB

标准的内存泄露。

#6


如果是很频烦的复申请释放内存,就有可能是内存碎片造成的.

#7


但是我开辟的空间都释放了呀
----------------

贴相关的代码才知道你是否释放了。

#8


GDI泄露吧?画图的话。打开资源管理器,查看,选择列,勾上GDI,跑跑程序看看是不是进程的GUI只增加不减少啊?。。

#9


谢谢各位的热心回答,以下是现实计算彩色图像直方图的代码:cvLoadImage与cvCreateImage是OpenCV库函数,RGBImg与GrayImg都是在头文件里面申明的IplImage*变量
void CHist::SetBmp(CString filename)
{
FileName=filename;
std::string Temp=(LPCSTR)FileName;
const char* ImgName=Temp.c_str();
if((RGBImg=cvLoadImage(ImgName,1))==NULL)
return;
GrayImg=cvCreateImage(cvGetSize(RGBImg),8,1);

Width=GrayImg->width;
Height=GrayImg->height;
ClearPixelCount();
GetHistData();

cvReleaseImage(&RGBImg);
cvReleaseImage(&GrayImg);
}
/********************************************************************************************************/
void  CHist::ReadBmp(CString filename)
{
std::string Temp=(LPCSTR)filename;
const char* ImgName=Temp.c_str();
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;

CFile* f;
f = new CFile();
f->Open(ImgName, CFile::modeRead);
f->SeekToBegin();
f->Read(&bmfh, sizeof(bmfh));
f->Read(&bmih, sizeof(bmih));

    // 分配图片像素内存
    RGBTRIPLE *rgb;
int index;
rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];
gray= new int[bmih.biWidth*bmih.biHeight];

f->SeekToBegin();
f->Seek(54,CFile::begin);                         // BMP 54个字节之后的是像素数据
f->Read(rgb, bmih.biWidth * bmih.biHeight * 3);   // 这里只读24位RGB(r,g,b)图像
f->Close();
FILE* fp;
fp=fopen("rgb2.txt","w");
fprintf(fp,"width=%ld\n",bmih.biWidth);
fprintf(fp,"height=%ld\n",bmih.biHeight);
for (int i=0;i<bmih.biHeight;i++)
{
for (int j=0;j<bmih.biWidth;j++)
{
index=i*bmih.biWidth+j;
gray[index]=(int)(rgb[index].rgbtBlue*0.114+rgb[index].rgbtGreen*0.587+rgb[index].rgbtRed*0.299);
fprintf(fp,"%d %d %d\n",rgb[index].rgbtBlue,rgb[index].rgbtGreen,rgb[index].rgbtRed);
}
fprintf(fp,"\n");
}
fclose(fp);
delete f;
delete rgb;
}
/********************************************************************************************************/
CSize CHist::GetBmpSize()
{
int x,y,w,h;
x=GetSystemMetrics(SM_CXFULLSCREEN);
y=GetSystemMetrics(SM_CYFULLSCREEN);
w=x/4;h=y/2;
if (x/4<Width || y/2<Height)
{
if (2*x/(4*y)>=Width/Height)
{
w=y/2*Width/Height;
h=y/2;
}
else
{
w=x/4;
y=x/4*Height/Width;
}
}
return CSize(w,h);
}
/********************************************************************************************************/
void CHist::DrawHist(CDC* pDC)
{
if (FileName!="")
{
CSize bmpsize=GetBmpSize();
MoveWindow(bmpsize.cx+10,0,300,bmpsize.cy);
CPen pen(PS_SOLID,1,RGB(0,0,255));
CPen *pOldpen;
pOldpen=pDC->SelectObject(&pen);
GetClientRect(&rect);
pDC->SetBkMode(TRANSPARENT);
/********************************************************************************************************/
pDC->MoveTo(rect.left+10,rect.bottom-10);
pDC->LineTo(rect.left+300,rect.bottom-10);

pDC->MoveTo(rect.left+10,rect.bottom-10);
pDC->LineTo(rect.left+10,rect.top+10);

pDC->MoveTo(rect.left+300,rect.bottom-10);
pDC->LineTo(rect.left+290,rect.bottom-15);
pDC->MoveTo(rect.left+300,rect.bottom-10);
pDC->LineTo(rect.left+290,rect.bottom-5);

pDC->MoveTo(rect.left+10,rect.top+10);
pDC->LineTo(rect.left+5,rect.top+20);
pDC->MoveTo(rect.left+10,rect.top+10);
pDC->LineTo(rect.left+15,rect.top+20);


pDC->MoveTo(rect.left+60,rect.bottom-10);
pDC->LineTo(rect.left+60,rect.bottom-3);
pDC->TextOut(rect.left+53,rect.bottom,"50");

pDC->MoveTo(rect.left+110,rect.bottom-10);
pDC->LineTo(rect.left+110,rect.bottom-3);
pDC->TextOut(rect.left+100,rect.bottom,"100");

pDC->MoveTo(rect.left+160,rect.bottom-10);
pDC->LineTo(rect.left+160,rect.bottom-3);
pDC->TextOut(rect.left+150,rect.bottom,"150");

pDC->MoveTo(rect.left+210,rect.bottom-10);
pDC->LineTo(rect.left+210,rect.bottom-3);
pDC->TextOut(rect.left+200,rect.bottom,"200");

pDC->MoveTo(rect.left+260,rect.bottom-10);
pDC->LineTo(rect.left+260,rect.bottom-3);
pDC->TextOut(rect.left+250,rect.bottom,"250");
pDC->TextOut(rect.left+5,rect.bottom-5,"0");
/********************************************************************************************************/
double temp;
for (int i=0;i<256;i++)
{
temp=(rect.Height()+10)*countpixel[i]/maxpixel;
pDC->MoveTo(rect.left+10+i,rect.bottom-10);
pDC->LineTo(rect.left+10+i,rect.Height()-(int)temp-10);
}
pDC->SelectObject(pOldpen);
/********************************************************************************************************/
}
}

/********************************************************************************************************/
void CHist::ClearPixelCount()
{
for (int i=0;i<256;i++)
{
countpixel[i]=0;
}
maxpixel=0;
}
/********************************************************************************************************/
void CHist::RGB2Gray(IplImage* src,IplImage* dst)
{
FILE* fp;
fp=fopen("rgb1.txt","w");
fprintf(fp,"width=%d\n",src->width);
fprintf(fp,"height=%d\n",src->height);
for (int i=0;i<src->height;i++)
{
uchar* ptr=(uchar*)(src->imageData+i*src->widthStep);
uchar* ptr2=(uchar*)(dst->imageData+i*dst->widthStep);
for (int j=0;j<src->width;j++)
{
ptr2[j]=ptr[3*j]*0.114+ptr[3*j+1]*0.587+ptr[3*j+2]*0.299;
fprintf(fp,"%d %d %d\n",ptr[3*j],ptr[3*j+1],ptr[3*j]+2);
}
fprintf(fp,"\n");
}
fclose(fp);
}

/********************************************************************************************************/
void CHist::GetHistData()
{
int temp;
RGB2Gray(RGBImg,GrayImg);
maxpixel=0;
for (int i=0;i<GrayImg->height;i++)
{
uchar* ptr=(uchar*)(GrayImg->imageData+i*GrayImg->widthStep);
for (int j=0;j<GrayImg->width;j++)
{
temp=ptr[j];
countpixel[temp]++;
if (countpixel[temp]>maxpixel)
{
maxpixel=countpixel[temp];
}
}
}
}
/********************************************************************************************************/
void  CHist::PixelNormalize()
{
for (int i=0;i<256;i++)
{
countpixel[i]=1.0*countpixel[i]/maxpixel;
}
}
/********************************************************************************************************/

void  CHist::NonNormalize()
{
for (int i=0;i<256;i++)
{
countpixel[i]=1.0*countpixel[i]*maxpixel;
}
}

/********************************************************************************************************/
void CHist::OnPaint() 
{
CPaintDC dc(this);
DrawHist(&dc);
}

#10


   补充一下,函数ReadBmp与RGB2Gray是用两种方法将RGB图像转化为Gray图像的,因为我怀疑是IplImage*指针没有释放造成的(但是程序中我明明释放了呀:cvReleaseImage()函数),不过目前ReadBmp有点问题,所以还未能证实我的想法

#11


为便于大家阅读,以下添加了一些注释:
if((RGBImg=cvLoadImage(ImgName,1))==NULL)    //根据文件名加载彩色图像
return; 
GrayImg=cvCreateImage(cvGetSize(RGBImg),8,1);//创建与彩色图像同样大小的灰度图模板

Width=GrayImg->width; 
Height=GrayImg->height; 
ClearPixelCount(); 
GetHistData(); //计算直方图数据

cvReleaseImage(&RGBImg); 
cvReleaseImage(&GrayImg); //释放图像指针
麻烦大家再帮我分析一下,谢谢!

#12


所有delete rgb; 改成delete []rgb;

#13


gray不知道你在哪儿删除的,但是,我觉的很容易出问题!如果要删除,一样要 delete[]gray;

#14


fandh你好!谢谢你的解答,这一点我确实疏忽了。但是我的问题在写函数ReadBmp之前就有了,所以与ReadBmp应该无关

#15


ReadBmp是我后来加上去的,只是为了做测试。但即使我不去调用ReadBmp,问题仍然存在

#16


pDC->SelectObject(pOldpen); 后,加一句:
pen.DeleteObject();

#17


啊!我去掉试试看

#18


看我急的,话都说错了。我加上试试看

#19


new [],要delete []

#20


仍然有问题呀,我现在没有用ReadBmp函数了,pen.DeleteObject();也用了。但是仍然消耗130MB内存。程序检索的图像有400幅,都是384*256的

#21


你当前的代码,看不出来那儿有问题,建议楼主自己单步调试!并且监视内存!

#22


有一次 我也遇到这种问题
甚至都怀疑其ADO的bug
一点点 一点点的 跟踪 测试
才发现 一直往一个集合类里写入 没有释放
。。。。
LZ还需仔细查验~

#1


你释放是最后关闭的时候释放还是运行过程中,不用就释放?
还有,你运行过程中申请的内存多么?

#2


可以使用内存池等防止反复申请释放内存》。。

#3


肯定是某些资源你没有及时释放造成的。还是再仔细检查一下吧。不妨把你用到的资源都是如何处理的描述一下。
特别是你加载图片的代码,不妨拿出来。

#4


把代码贴出来看看

#5


而我的程序每次都增加几十KB

标准的内存泄露。

#6


如果是很频烦的复申请释放内存,就有可能是内存碎片造成的.

#7


但是我开辟的空间都释放了呀
----------------

贴相关的代码才知道你是否释放了。

#8


GDI泄露吧?画图的话。打开资源管理器,查看,选择列,勾上GDI,跑跑程序看看是不是进程的GUI只增加不减少啊?。。

#9


谢谢各位的热心回答,以下是现实计算彩色图像直方图的代码:cvLoadImage与cvCreateImage是OpenCV库函数,RGBImg与GrayImg都是在头文件里面申明的IplImage*变量
void CHist::SetBmp(CString filename)
{
FileName=filename;
std::string Temp=(LPCSTR)FileName;
const char* ImgName=Temp.c_str();
if((RGBImg=cvLoadImage(ImgName,1))==NULL)
return;
GrayImg=cvCreateImage(cvGetSize(RGBImg),8,1);

Width=GrayImg->width;
Height=GrayImg->height;
ClearPixelCount();
GetHistData();

cvReleaseImage(&RGBImg);
cvReleaseImage(&GrayImg);
}
/********************************************************************************************************/
void  CHist::ReadBmp(CString filename)
{
std::string Temp=(LPCSTR)filename;
const char* ImgName=Temp.c_str();
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;

CFile* f;
f = new CFile();
f->Open(ImgName, CFile::modeRead);
f->SeekToBegin();
f->Read(&bmfh, sizeof(bmfh));
f->Read(&bmih, sizeof(bmih));

    // 分配图片像素内存
    RGBTRIPLE *rgb;
int index;
rgb = new RGBTRIPLE[bmih.biWidth*bmih.biHeight];
gray= new int[bmih.biWidth*bmih.biHeight];

f->SeekToBegin();
f->Seek(54,CFile::begin);                         // BMP 54个字节之后的是像素数据
f->Read(rgb, bmih.biWidth * bmih.biHeight * 3);   // 这里只读24位RGB(r,g,b)图像
f->Close();
FILE* fp;
fp=fopen("rgb2.txt","w");
fprintf(fp,"width=%ld\n",bmih.biWidth);
fprintf(fp,"height=%ld\n",bmih.biHeight);
for (int i=0;i<bmih.biHeight;i++)
{
for (int j=0;j<bmih.biWidth;j++)
{
index=i*bmih.biWidth+j;
gray[index]=(int)(rgb[index].rgbtBlue*0.114+rgb[index].rgbtGreen*0.587+rgb[index].rgbtRed*0.299);
fprintf(fp,"%d %d %d\n",rgb[index].rgbtBlue,rgb[index].rgbtGreen,rgb[index].rgbtRed);
}
fprintf(fp,"\n");
}
fclose(fp);
delete f;
delete rgb;
}
/********************************************************************************************************/
CSize CHist::GetBmpSize()
{
int x,y,w,h;
x=GetSystemMetrics(SM_CXFULLSCREEN);
y=GetSystemMetrics(SM_CYFULLSCREEN);
w=x/4;h=y/2;
if (x/4<Width || y/2<Height)
{
if (2*x/(4*y)>=Width/Height)
{
w=y/2*Width/Height;
h=y/2;
}
else
{
w=x/4;
y=x/4*Height/Width;
}
}
return CSize(w,h);
}
/********************************************************************************************************/
void CHist::DrawHist(CDC* pDC)
{
if (FileName!="")
{
CSize bmpsize=GetBmpSize();
MoveWindow(bmpsize.cx+10,0,300,bmpsize.cy);
CPen pen(PS_SOLID,1,RGB(0,0,255));
CPen *pOldpen;
pOldpen=pDC->SelectObject(&pen);
GetClientRect(&rect);
pDC->SetBkMode(TRANSPARENT);
/********************************************************************************************************/
pDC->MoveTo(rect.left+10,rect.bottom-10);
pDC->LineTo(rect.left+300,rect.bottom-10);

pDC->MoveTo(rect.left+10,rect.bottom-10);
pDC->LineTo(rect.left+10,rect.top+10);

pDC->MoveTo(rect.left+300,rect.bottom-10);
pDC->LineTo(rect.left+290,rect.bottom-15);
pDC->MoveTo(rect.left+300,rect.bottom-10);
pDC->LineTo(rect.left+290,rect.bottom-5);

pDC->MoveTo(rect.left+10,rect.top+10);
pDC->LineTo(rect.left+5,rect.top+20);
pDC->MoveTo(rect.left+10,rect.top+10);
pDC->LineTo(rect.left+15,rect.top+20);


pDC->MoveTo(rect.left+60,rect.bottom-10);
pDC->LineTo(rect.left+60,rect.bottom-3);
pDC->TextOut(rect.left+53,rect.bottom,"50");

pDC->MoveTo(rect.left+110,rect.bottom-10);
pDC->LineTo(rect.left+110,rect.bottom-3);
pDC->TextOut(rect.left+100,rect.bottom,"100");

pDC->MoveTo(rect.left+160,rect.bottom-10);
pDC->LineTo(rect.left+160,rect.bottom-3);
pDC->TextOut(rect.left+150,rect.bottom,"150");

pDC->MoveTo(rect.left+210,rect.bottom-10);
pDC->LineTo(rect.left+210,rect.bottom-3);
pDC->TextOut(rect.left+200,rect.bottom,"200");

pDC->MoveTo(rect.left+260,rect.bottom-10);
pDC->LineTo(rect.left+260,rect.bottom-3);
pDC->TextOut(rect.left+250,rect.bottom,"250");
pDC->TextOut(rect.left+5,rect.bottom-5,"0");
/********************************************************************************************************/
double temp;
for (int i=0;i<256;i++)
{
temp=(rect.Height()+10)*countpixel[i]/maxpixel;
pDC->MoveTo(rect.left+10+i,rect.bottom-10);
pDC->LineTo(rect.left+10+i,rect.Height()-(int)temp-10);
}
pDC->SelectObject(pOldpen);
/********************************************************************************************************/
}
}

/********************************************************************************************************/
void CHist::ClearPixelCount()
{
for (int i=0;i<256;i++)
{
countpixel[i]=0;
}
maxpixel=0;
}
/********************************************************************************************************/
void CHist::RGB2Gray(IplImage* src,IplImage* dst)
{
FILE* fp;
fp=fopen("rgb1.txt","w");
fprintf(fp,"width=%d\n",src->width);
fprintf(fp,"height=%d\n",src->height);
for (int i=0;i<src->height;i++)
{
uchar* ptr=(uchar*)(src->imageData+i*src->widthStep);
uchar* ptr2=(uchar*)(dst->imageData+i*dst->widthStep);
for (int j=0;j<src->width;j++)
{
ptr2[j]=ptr[3*j]*0.114+ptr[3*j+1]*0.587+ptr[3*j+2]*0.299;
fprintf(fp,"%d %d %d\n",ptr[3*j],ptr[3*j+1],ptr[3*j]+2);
}
fprintf(fp,"\n");
}
fclose(fp);
}

/********************************************************************************************************/
void CHist::GetHistData()
{
int temp;
RGB2Gray(RGBImg,GrayImg);
maxpixel=0;
for (int i=0;i<GrayImg->height;i++)
{
uchar* ptr=(uchar*)(GrayImg->imageData+i*GrayImg->widthStep);
for (int j=0;j<GrayImg->width;j++)
{
temp=ptr[j];
countpixel[temp]++;
if (countpixel[temp]>maxpixel)
{
maxpixel=countpixel[temp];
}
}
}
}
/********************************************************************************************************/
void  CHist::PixelNormalize()
{
for (int i=0;i<256;i++)
{
countpixel[i]=1.0*countpixel[i]/maxpixel;
}
}
/********************************************************************************************************/

void  CHist::NonNormalize()
{
for (int i=0;i<256;i++)
{
countpixel[i]=1.0*countpixel[i]*maxpixel;
}
}

/********************************************************************************************************/
void CHist::OnPaint() 
{
CPaintDC dc(this);
DrawHist(&dc);
}

#10


   补充一下,函数ReadBmp与RGB2Gray是用两种方法将RGB图像转化为Gray图像的,因为我怀疑是IplImage*指针没有释放造成的(但是程序中我明明释放了呀:cvReleaseImage()函数),不过目前ReadBmp有点问题,所以还未能证实我的想法

#11


为便于大家阅读,以下添加了一些注释:
if((RGBImg=cvLoadImage(ImgName,1))==NULL)    //根据文件名加载彩色图像
return; 
GrayImg=cvCreateImage(cvGetSize(RGBImg),8,1);//创建与彩色图像同样大小的灰度图模板

Width=GrayImg->width; 
Height=GrayImg->height; 
ClearPixelCount(); 
GetHistData(); //计算直方图数据

cvReleaseImage(&RGBImg); 
cvReleaseImage(&GrayImg); //释放图像指针
麻烦大家再帮我分析一下,谢谢!

#12


所有delete rgb; 改成delete []rgb;

#13


gray不知道你在哪儿删除的,但是,我觉的很容易出问题!如果要删除,一样要 delete[]gray;

#14


fandh你好!谢谢你的解答,这一点我确实疏忽了。但是我的问题在写函数ReadBmp之前就有了,所以与ReadBmp应该无关

#15


ReadBmp是我后来加上去的,只是为了做测试。但即使我不去调用ReadBmp,问题仍然存在

#16


pDC->SelectObject(pOldpen); 后,加一句:
pen.DeleteObject();

#17


啊!我去掉试试看

#18


看我急的,话都说错了。我加上试试看

#19


new [],要delete []

#20


仍然有问题呀,我现在没有用ReadBmp函数了,pen.DeleteObject();也用了。但是仍然消耗130MB内存。程序检索的图像有400幅,都是384*256的

#21


你当前的代码,看不出来那儿有问题,建议楼主自己单步调试!并且监视内存!

#22


有一次 我也遇到这种问题
甚至都怀疑其ADO的bug
一点点 一点点的 跟踪 测试
才发现 一直往一个集合类里写入 没有释放
。。。。
LZ还需仔细查验~