关于内存泄漏有一问,问题其实很土!

lifeequation 2003-08-12 09:57:07
最近在看到《深入浅出mfc》时看到候先生的例子scribble中,有这么一个函数
CStroke* CScribbleDoc::NewStroke()
{
CStroke* pStrokeItem = new CStroke(m_nPenWidth);
m_strokeList.AddTail(pStrokeItem);
SetModifiedFlag(); // Mark the document as having been modified, for
// purposes of confirming File Close.
return pStrokeItem;
}

这个地方我有点不明白,为什么他new了一个CStroke对象,在程序中却没有delete它,但是事实上它并没有内存泄漏,但是我也是仿造它写的,我却提示有内存泄漏,大家能帮我讲解一下吗?谢谢!
...全文
55 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
lifeequation 2003-08-12
  • 打赏
  • 举报
回复
horin153(horin):
你好!
关键是程序调用CScribbleDoc::DeleteContents()时才一次性delete,是有
条件的,也就是你要重菜单上点击那个“clear all”菜单项。否则是不会调
到CScribbleDoc::DeleteContents()这个函数的,所以也就没有delete了,
然而它也不会造成内存泄漏!
我还是不明白它为什么不会造成内存泄漏?
大家帮帮忙吧???
horin153 2003-08-12
  • 打赏
  • 举报
回复
这个例子是不会内存泄漏的.我以前也怀疑过此例子,但经测试,的确正确无泄漏.
1,pStrokeItem是CScribbleDoc::NewStroke()的返回值,需要保存在文档的m_strokeList链表中,而此链表在程序未结束前是始终存在的(当然,你自己可以中途清空),也就是只new而不delete.直到程序调用CScribbleDoc::DeleteContents()时才一次性delete.
2,delete m_strokeList.RemoveHead();可以彻底清除链表,而无内存泄漏!!!
3,从以上两点可知,从整个程序的角度看,是没有内存泄漏的.
lifeequation 2003-08-12
  • 打赏
  • 举报
回复
likangnian0128(likangnian0128) 兄:
谢谢了,
DeleteContents()函数只是在清除的时候才会调用阿,如果正常退出(没有清除掉
所画的图形)的画,它是没有调用DeleteContents()函数的,我查遍了它的整个
程序,也没有发现在什么地方delete掉这个指针了;
zeroweb() 兄:
谢谢了,
你说的“一般来说是在CScribbleDoc类析构时把链表中的对象一个一个的析构、删除掉,链表清空,这样肯定就不会有momery leak的" ,没错阿,但是候先生的例子根本就没有这么做,但是也没有内存泄漏的事情发生,这是怎么回事?另外一方面,这个链表是要
归档的,这样在文档类析构函数中把它们提出并delete掉,对以后打开文件继续操作有没有影响阿?



lashengcrh 2003-08-12
  • 打赏
  • 举报
回复
如何用VC工具检查到内存的泄露情况?
likangnian0128 2003-08-12
  • 打赏
  • 举报
回复
我想是在这里:

SCRIBBLEDOC.CPP

#0085 void CScribbleDoc::DeleteContents()
#0086 {
#0087 while (!m_strokeList.IsEmpty())
#0088 {
#0089 delete m_strokeList.RemoveHead();
//here~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#0090 }
#0091 CDocument::DeleteContents();
#0092 }
#0093
zeroweb 2003-08-12
  • 打赏
  • 举报
回复
new出了CStroke对象之后,加到一个链表中管理,这样在这个类CScribbleDoc的对象生存期间内,CStroke对象可随时从链表中取出来使用。一般来说是在CScribbleDoc类析构时把链表中的对象一个一个的析构、删除掉,链表清空。这样肯定就不会有momery leak的。
canany1tellme 2003-08-12
  • 打赏
  • 举报
回复
指针放到m_strokeList里边,你可以查找CScribbleDoc类的其他成员函数,有没有从m_strokeList取出指针delete掉。
zerphy 2003-08-12
  • 打赏
  • 举报
回复
在以后的使用过程中,被delete了吧
会思考的草 2003-08-12
  • 打赏
  • 举报
回复
new操作符是在堆上分配内存的,只要指针pStrokeItem不丢失或者被销毁,那么在程序退出之前,或者在改变pStrokeItem的值之前,随时都可以delete的。
lifeequation 2003-08-12
  • 打赏
  • 举报
回复
up,自己顶一下,大家帮个忙吧
lifeequation 2003-08-12
  • 打赏
  • 举报
回复
谢谢各位了,问题在DeleteContents()函数上,这个函数由
OnNewDocument()和OnOpenDocument()及OnCloseDocument()默认调用,
所以最终new出来的对象是可以被Delete的,谢谢了,这样久不会有内存泄漏了,
否则就有,我测试过了,真是土阿,居然不知道DeleteContents()是CDocument的一个
成员函数,真是faint!
likangnian0128 2003-08-12
  • 打赏
  • 举报
回复
在microsoft visual studio\vc98\mfc\src目录,LIST_O.CPP,
CObList的实现:(定义在同一目录的AFXCOLL.H)

void CObList::RemoveAll()
{
ASSERT_VALID(this);

// destroy elements


m_nCount = 0;
m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
m_pBlocks->FreeDataChain();
m_pBlocks = NULL;
}

CObList::~CObList()
{
RemoveAll();
ASSERT(m_nCount == 0);
}

CObList析构时候自动删除其下的CObject,所以直接推出也没有内存泄漏。
likangnian0128 2003-08-12
  • 打赏
  • 举报
回复
可以在CScribbleDoc::DeleteContents()里设置一个断点,看它直接退出的时候会不会调用
CScribbleDoc::DeleteContents()。

还有,我想:
CTypedPtrList<CObList,CStroke*> m_strokeList;
m_strokeList是CObList的实例,如果CObList析构的时候会清除自己列表里的CObject实例,那么就不会有内存泄漏。
taianmonkey 2003-08-12
  • 打赏
  • 举报
回复
其实在程序中new出的内存可以在销毁处理时一起删除!

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧