那么说,应该是MFC的错了!

Tasehouny 2001-04-22 11:55:00
原标题内容太长了,换页,原题见: http://www.csdn.net/expert/topic/102/102243.shtm

那么说,应该是MFC的错了,因为CObList这个类在MFC中提供了Serializ方法,但是在MSDN中却没有出现?也许MFC的程序员发现这个Serializ函数有问题,所以不敢写出来,既然MFC中有这个东西,我那样调用也不算错,只是因为这个东西本身就是有问题的。

MFC中CObList的Serializ方法如下:
文件路径在.../.../VC98/MFC/SRC/LIST_O.CPP
/////////////////////////////////////////////////////////////////////////////
// Serialization

void CObList::Serialize(CArchive& ar)
{
ASSERT_VALID(this);

CObject::Serialize(ar);

if (ar.IsStoring())
{
ar.WriteCount(m_nCount);
for (CNode* pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)
{
ASSERT(AfxIsValidAddress(pNode, sizeof(CNode)));
ar << pNode->data;
}
}
else
{
DWORD nNewCount = ar.ReadCount();
CObject* newData;
while (nNewCount--)
{
ar >> newData;
AddTail(newData);
}
}
}

请大家帮我证明这个函数确实有问题。
...全文
97 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tasehouny 2001-04-24
  • 打赏
  • 举报
回复
To :tsingbo
把您写的文章发给我好么?侯先生的书我读了,受益非浅
tsingbo 2001-04-24
  • 打赏
  • 举报
回复
已经寄出
tsingbo 2001-04-23
  • 打赏
  • 举报
回复
我还没有看你的代码。好吧,我下载来看看。
不过CObList::Serialize不会有问题。如果你对系列化的机制有兴趣,我刚好写过这方面的文章,可以寄给你看看。或者你也可以看看侯先生的《深入浅出MFC》.
tsingbo 2001-04-23
  • 打赏
  • 举报
回复
CObList的Serialize函数没有任何问题。
joke100 2001-04-23
  • 打赏
  • 举报
回复
如果不在外层加以处理(先清空再读取)

如果连续调用这个函数,
假设程序没有发生内存冲突,那么调用三次后链表里的成员数目就是实际的三倍,因为它只管ADDTAIL...

有兴趣也可以试一下在其中一台机器上存盘,然后去另外一台机器上运行后LOAD,或者重启机器后运行不同的软件环境....

joke100 2001-04-23
  • 打赏
  • 举报
回复

老兄自己看一看读取部分的代码就是了
DWORD nNewCount = ar.ReadCount();
CObject* newData;
while (nNewCount--)
{
ar >> newData;
AddTail(newData);
}
这就如同类的默认拷贝初始化函数一样,给你一个默认的浅拷贝.
实际应用时多数要重载成深拷贝的形式...

ar >> newData;这一句是读出了一个指针值,也就是一个四字节的地址,而不是指针指向的内容,我们知道指针是不能存盘的(不能保证每次运行程序分配同样的地址),假设你运行其他程序占用了这块内存区域,那么将是什么后果呢?

你可以看一看微软定义的很多结构,第一个成员都是本结构的大小,这样一方面可以由程序员灵活操纵,另一方面可以通过读取时按长度决定区域内容,进而实现版本的向后兼容...

joke100 2001-04-23
  • 打赏
  • 举报
回复

老兄自己看一看读取部分的代码就是了
DWORD nNewCount = ar.ReadCount();
CObject* newData;
while (nNewCount--)
{
ar >> newData;
AddTail(newData);
}
这就如同类的默认拷贝初始化函数一样,给你一个默认的浅拷贝.
实际应用时多数要重载成深拷贝的形式...

ar >> newData;这一句是读出了一个指针值,也就是一个四字节的地址,而不是指针指向的内容,我们知道指针是不能存盘的(不能保证每次运行程序分配同样的地址),假设你运行其他程序占用了这块内存区域,那么将是什么后果呢?

你可以看一看微软定义的很多结构,第一个成员都是本结构的大小,这样一方面可以由程序员灵活操纵,另一方面可以通过读取时按长度决定区域内容,进而实现版本的向后兼容...

Tasehouny 2001-04-23
  • 打赏
  • 举报
回复
还有MFC读的部分:
DWORD nNewCount = ar.ReadCount();
CObject* newData;
while (nNewCount--)
{
ar >> newData;
AddTail(newData);
}

ar >> newData; 实际上是将文件流中的地址传送给newData,而这个流地址使FILE等这些东西装入文件后在内存中的地址,这个地址是动态决定的,而不是静态的。
不知道我理解的是否对?
Tasehouny 2001-04-23
  • 打赏
  • 举报
回复
TO:tsingbo(tsingbo) 
CObList的Serialize函数没有任何问题,您的根据是什么?你有好的解决方案?

TO:joke100(joke100) 
再次向您致敬,但您给的那段代码仍然不能编译通过?
void CCaseFile::Serialize(CArchive &ar)
{
int nCount = 0, i = 0;
CFieldProperty* pTemp = NULL;

if (ar.IsStoring())
{
ar << m_iVerNum << m_sSQL
<< m_sMemo << m_iCurSel << m_iConSel;

nCount = pOblist->GetCount();
ar << nCount;
for (i = 0; i < nCount; i++)
{
pTemp = (CFieldProperty*)pOblist->GetAt(pOblist->FindIndex(i));
pTemp->Serialize(ar);
}
}
else
{
ar >> m_iVerNum >> m_sSQL
>> m_sMemo >> m_iCurSel >> m_iConSel ;

while (pOblist->GetCount())
delete (CFieldProperty*)pOblist->RemoveTail(); //这行有错!
ar >> nCount;
for (i = 0; i < nCount; i++)
{
pTemp = new CFieldProperty();
pTemp->Serialize(ar);
pOblist->AddTail(pTemp);
}
}
}
如果把那行换成 pOblist->RemoveAll()仍然出内存泄漏的错误!
tsingbo 2001-04-23
  • 打赏
  • 举报
回复
我将改动后的工程发给你了。
要看看我改动的内容,在工程中搜索字符串: tsingbo

16,467

社区成员

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

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

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