建立一个MFC Wizard文档,我写了一个非常简陋的汉诺塔程序,但是有时候出现内存泄漏的错误,请大侠们指点!
/////////////stock.h////////////////////
#include "stdafx.h"
#define n 7struct Block
{
int    layer;
int    centre;
int    length;
CRect  rect;
};class Stock
{
public:
Block b[n];
int ;
int layer;
Stock() {layer=0;=0;}
void drawstock(int _,CDC* pDC);
void displayblock(Block b,CDC* pDC);
void undisplayblock(Block b,CDC* pDC);
void move(Stock& s,CDC* pDC);
};
/////////////stock.cpp///////////////////////
#include "stdafx.h"
#include "stock.h"
#include<math.h>void Stock::drawstock(int _,CDC* pDC)
{
CPen pen;
pen.DeleteObject();
pen.CreatePen(PS_SOLID,7,RGB(0,0,0));
pDC->SelectObject(pen);
pDC->MoveTo(130+_*170,50);
pDC->LineTo(130+_*170,250);
pen.DeleteObject();
};void Stock::displayblock(Block b,CDC *pDC)
{
CBrush brush;
CPen pen;
pen.DeleteObject();
pen.CreatePen(PS_SOLID,1,RGB(0,0,0));
pDC->SelectObject(pen);
brush.DeleteObject();
brush.CreateSolidBrush(RGB(0,0,0));
pDC->FillRect(b.rect,&brush);
layer++;
pen.DeleteObject();
brush.DeleteObject();
};void Stock::undisplayblock(Block b,CDC *pDC)
{
CBrush brush;
CPen pen;
pen.DeleteObject();
pen.CreatePen(PS_SOLID,1,RGB(255,255,255));
pDC->SelectObject(pen);
brush.DeleteObject();
brush.CreateSolidBrush(RGB(255,255,255));
pDC->FillRect(b.rect,&brush);
drawstock(,pDC);
pen.DeleteObject();
brush.DeleteObject();
layer--;
};void Stock::move(Stock& s,CDC* pDC)
{
float j;
for(int i=0;i<300000;i++)
j=log(exp(j*j*j));
undisplayblock(b[layer-1],pDC); s.b[s.layer].length=b[layer].length;
s.b[s.layer].centre=130+s.*170;
s.b[s.layer].rect.bottom=250-7*s.layer;
s.b[s.layer].rect.top=s.b[s.layer].rect.bottom-7;
s.b[s.layer].rect.right=s.b[s.layer].centre+s.b[s.layer].length;
s.b[s.layer].rect.left=s.b[s.layer].centre-s.b[s.layer].length; s.displayblock(s.b[s.layer],pDC);
}//HinoiiView.h中添加了
public:
      Stock s[3];
      void f(int nn,Stock& x,Stock& y,Stock& z,CDC* pDC);//HinoiiView.cpp中添加了
COhniiView::COhniiView()
{
for(int i=0;i<n;i++)
{
s[0].b[i].centre=130;
s[0].b[i].length=60-7*i;
s[0].b[i].rect.bottom=250-7*i;
s[0].b[i].rect.left=s[0].b[i].centre-s[0].b[i].length;
s[0].b[i].rect.right=s[0].b[i].centre+s[0].b[i].length;
s[0].b[i].rect.top=s[0].b[i].rect.bottom-7;
}
}void COhniiView::OnDraw(CDC* pDC)
{
COhniiDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
s[0].=0;
s[1].=1;
s[2].=2;
s[0].drawstock(0,pDC);
s[1].drawstock(1,pDC);
s[2].drawstock(2,pDC);
for(int i=0;i<n;i++)
s[0].displayblock(s[0].b[i],pDC);}void COhniiView::OnRButtonUp(UINT nFlags, CPoint point) 
{
CDC* pDC=GetDC();
f(n,s[0],s[1],s[2],pDC);
CView::OnRButtonUp(nFlags, point);
}void COhniiView::f(int nn,Stock& x,Stock& y,Stock& z,CDC* pDC)
{
if(nn>0) {
f(nn-1,x,z,y,pDC);
x.move(y,pDC);
f(nn-1,z,y,x,pDC);
}
};

解决方案 »

  1.   

    gdi bug 的问题吧,尽量避免重复创建 gdi 对象,把所有的 CPen, CBrush 都放在类成员里,只创建一次,然后在函数里重复使用。
      

  2.   

    如果有的话应该的在你对CPen,CBrush的处理上,一般来说我们并不直接引用CPen和CBrush的DeleteObject()来释放内存,正确的方法应该是:CPen pen(PS_SOLID, 1, RGB(r, g, b)), *pOldPen;
    pOldPen = pDC->SelectObject(&pen);
    //以下是绘图部分
    ...
    ...
    ...
    //删除
    pDC->SelectObject(pOldPen);删除CBrush是完全一样的
      

  3.   

    你  cdc select的新笔  返回的旧笔 没有 在结束是select 回去
      

  4.   

    to ayi7456(阿一)
    请解释一下为什么不直接用pen调用delete?
    to zhangyilan(数字通信) 
    BoundsCheck是什么东西。真惨,我们这个学期要搞图形学,现在马上就要用MFC来画图。有很多不明白的地方,尤其是
    MFC庞大的类库和复杂的继承关系。我看过《深入简出MFC》,但是由于当时缺少上机时间只看到80%就看不下去了。
      

  5.   

    void Stock::drawstock(int _,CDC* pDC)
    {
    1 CPen pen;
    2 pen.DeleteObject();
    3 pen.CreatePen(PS_SOLID,7,RGB(0,0,0));
    4 pDC->SelectObject(pen);
    5 pDC->MoveTo(130+_*170,50);
    6 pDC->LineTo(130+_*170,250);
    7 pen.DeleteObject();
    };绘图完毕以后没有释放资源
    你虽然用了pen.DeleteObject();但是因为他还处于被选中的状态,这里资源泄漏了建议第4行 保存返回的绘图对象
    第6,7行中重新选回去看了一下,这个问题不单单是这一个地方
      

  6.   

    楼上说的对,CPen,CBrush一般只需调用SelectObject(poldpen)而不用调用DeleteObject()
    对不对
      

  7.   

    如果我不把选中的PEN删除
    pDC->selectObject(&pen);
    而没有pDC->selectObject(oldpen);
    当这个过程结束的时候pen会自己析够,这样pDC中的pen会如何?
      

  8.   

    在程序进行当中,我想加入键盘控制,如
    void COhniiView::f(int nn,Stock& x,Stock& y,Stock& z,CDC* pDC)
    {
    if(nn>0) {
    f(nn-1,x,z,y,pDC);
                      if no_Key_pressed {x.move(y,pDC);}
    f(nn-1,z,y,x,pDC);
    }
    };
    no_Key_pressed 应该用什么函数?
      

  9.   

    void Stock::drawstock(int _,CDC* pDC)
    {
    CPen pen, *pOldPen;
    //2 pen.DeleteObject();
    3 pen.CreatePen(PS_SOLID,7,RGB(0,0,0));
    4 pOldPen = pDC->SelectObject(&pen);
    5 pDC->MoveTo(130+_*170,50);
    6 pDC->LineTo(130+_*170,250);
    7 pDC->SelectObject(pOldPen);  
    // 不回复原来的话,这里定义的pen北系统使用,下面的这段就无法使用
      pen.DeleteObject();
    };
      

  10.   

    其实你自己定义的pen不调用DeleteObject 也可以的。局部变量在函数退出的时候可以可以自己删除,但是前提条件是他们没有被系统所使用。
    你的代码当中,没有把画笔恢复成为原来的设置,系统就一直使用你局部变量上指定的画笔,因此在退出函数的时候无法释放这个变量,你的那个删除命令根本就不起作用。
    看 vc帮助,那里明确地说明了使用当中的对象是无法删除的。
      

  11.   

    CDC* pDC=GetDC();
    f(n,s[0],s[1],s[2],pDC);
    CView::OnRButtonUp(nFlags, point);记得ReleaseDC(pDC);
      

  12.   


      我倒有个方法,不知道对不对
      你在程序中设一个中间变量myFlag,初始化为0;
      
      {
           代码1
           
           while(myFlag==0)
           {
             用来等待呀
           }
           myFlag=1;
           代码2
           while(myFlag==0)
           {
             用来等待呀
           }
           
       }在鼠标单击时把myFlag执为非0,然后刷新,这不就实现了停停走走。