Stack overflow while serializing large object network in MFC
Bart van Haaff -- BARTHAAF@docuaccess.nl
Tuesday, November 26, 1996
Environment: MSVC1.52, NT4.0
Hi,
I try to serialize a pretty large and complex network of objects using
MFC's serialize method. This works fine for me until a certain limit in
the number of objects has been reached, My app crashes because of a stack
overflow (current stack size 42 Kb, and I do not have any more space in
the data segment).
I have tried the following code to enlarge stack but this crashes on the
statement:
ar >> m_pRootObject;
The crash happens immediate when I hit 'Step into (F8)' in the debugger.
// testcode
void CMyDoc::Serialize(CArchive& ar)
{
// save some things in statics to survive stack switch
static CMyRootClass* pRootObject=NULL;
static CString strFileName=GetPathName();
HANDLE hStack=GlobalAlloc(GPTR,63L*1024L);
LPSTR pStack=(LPSTR)GlobalLock(hStack);
// some obscure win3.0 API call
SwitchStackTo(HIWORD(pStack),(UINT)(63L*1024L),0);
// normal serialize code
CFile f;
if(f.Open(strFileName, CFile::modeRead))
{
CArchive ar(&f,CArchive::load);
// hit F8 to crash.....
ar >> m_pRootObject;
}
ar.Close();
f.Close();
SwitchStackBack();
GlobalUnlock(hStack);
GlobalFree(hStack);
}
The nature of serialize() is recursive and there is not much to do about
that, I checked out MFC's source code and the CArchive and CRuntimeClass
read/write code, there are some non-static local variables in the code
that eat a little stack space for each recursive level. In my own
serialize code I declared all locals as 'static'.
I hope somebody can give some tips/hints, please don't tell me to:
* use 32-bits (I know, but my customers don't)
* change the structure of my object model (its to late for that)
* stop using MFC (I like some parts of it)
Thanks a lot....
Bart van Haaff (barthaaf@docuaccess.nl)
Senior Software Developer
Document Access B.V.
The Netherlands
Alexander Sasha Grinshpun -- alexgr@mercury.co.il
Thursday, November 28, 1996
You don't have to change your object model, just change the way your
network of objects are serialized. Let's take a look at pseudocode of
serializing a graph.
class Node {
SomeUsefullData data;
ListOfPointersToEdge edges;
Serialize(CArchive &ar) {
data.Serialize(ar);
edges.Serialize(ar); // (1)
};
};
class Edge {
Node *source;
Node *target;
Serialize(CArchive &ar) {
if(ar.IsLoading()) {
ar >> source;
// Here we may enter into a deep recursion because target may be
// not serialized yet
ar >> target;
} else {
ar << source;
ar << target;
}
}
};
class Graph {
ListOfPointerToNodes nodes;
Serialize(CArchive &ar) {
nodes.Serialize(ar);
}
};
Such a serialization of the Graph will cause a deep Serialize recursion.
The cause of this recursion is serialization of the edges of the node
inside the node itself. The following change in serialization will
fix the problem:
Node::Serialize(ar) {
// We are serializing just a data and delegating responsibility
// of graph structure serializing to Graph itself
data.Serialize(ar);
}
Graph::Serialize(ar) {
nodes.Serialize();
// Pay attention, that here we will not enter a deep recursion in the
// edge serialization because all nodes are already serialized
for eache pnode in nodes {
pnode->edges.Serialize();
}
}
I hope it's helpful for you.
--
Sasha.
Bart van Haaff wrote:
>
> Environment: MSVC1.52, NT4.0
>
> Hi,
>
> I try to serialize a pretty large and complex network of objects using
> MFC's serialize method. This works fine for me until a certain limit in
> the number of objects has been reached, My app crashes because of a stack
> overflow (current stack size 42 Kb, and I do not have any more space in
> the data segment).
>
> I have tried the following code to enlarge stack but this crashes on the
> statement:
> ar >> m_pRootObject;
>
> The crash happens immediate when I hit 'Step into (F8)' in the debugger.
>
> // testcode
> void CMyDoc::Serialize(CArchive& ar)
> {
> // save some things in statics to survive stack switch
> static CMyRootClass* pRootObject=NULL;
> static CString strFileName=GetPathName();
>
> HANDLE hStack=GlobalAlloc(GPTR,63L*1024L);
> LPSTR pStack=(LPSTR)GlobalLock(hStack);
> // some obscure win3.0 API call
> SwitchStackTo(HIWORD(pStack),(UINT)(63L*1024L),0);
> // normal serialize code
> CFile f;
> if(f.Open(strFileName, CFile::modeRead))
> {
> CArchive ar(&f,CArchive::load);
> // hit F8 to crash.....
> ar >> m_pRootObject;
> }
> ar.Close();
> f.Close();
> SwitchStackBack();
> GlobalUnlock(hStack);
> GlobalFree(hStack);
> }
>
> The nature of serialize() is recursive and there is not much to do about
> that, I checked out MFC's source code and the CArchive and CRuntimeClass
> read/write code, there are some non-static local variables in the code
> that eat a little stack space for each recursive level. In my own
> serialize code I declared all locals as 'static'.
>
> I hope somebody can give some tips/hints, please don't tell me to:
> * use 32-bits (I know, but my customers don't)
> * change the structure of my object model (its to late for that)
> * stop using MFC (I like some parts of it)
>
> Thanks a lot....
>
> Bart van Haaff (barthaaf@docuaccess.nl)
> Senior Software Developer
> Document Access B.V.
> The Netherlands
--
----
Thanks,
Sasha.
rick cameron -- rick_cameron@msn.com
Thursday, November 28, 1996
We had a similar problem. Our solution was to change the serialization code.
Our document contains a list of sections; each section has a list of objects.
An object may be attached to a guideline, and a guideline may connect objects
in several sections.
We found that the following was happening:
document serializes first section
section serializes objects
object serializes guideline
guideline serializes all attached objects (which may jump into another
section)
object serializes its section
section serializes objects
...etc...
It was possible for all objects to be serialized as a result of the call to
serialize the first section - and, if there were several guidelines, recursion
could become quite deep.
The solution was to change the Serialize member of the guideline class so that
it didn't serialize its attached objects. When loading the document, each
object reattaches itself to its guideline.
The reason I've gone into some detail is to point out that there may be a way
that you can change your serialization code to reduce the amount of
cross-coupling and recursion, without changing your object model. Instead of
serializing a pointer to an object, reconnect when loading.
- rick
owner-mfc-l@majordomo.netcom.com on behalf of Bart van Haaff wrote:
>
> Environment: MSVC1.52, NT4.0
>
> Hi,
>
> I try to serialize a pretty large and complex network of objects using
> MFC's serialize method. This works fine for me until a certain limit in
> the number of objects has been reached, My app crashes because of a stack
> overflow (current stack size 42 Kb, and I do not have any more space in
> the data segment).
>
> I have tried the following code to enlarge stack but this crashes on the
> statement:
> ar >> m_pRootObject;
>
> The crash happens immediate when I hit 'Step into (F8)' in the debugger.
>
> // testcode
> void CMyDoc::Serialize(CArchive& ar)
> {
> // save some things in statics to survive stack switch
> static CMyRootClass* pRootObject=NULL;
> static CString strFileName=GetPathName();
>
> HANDLE hStack=GlobalAlloc(GPTR,63L*1024L);
> LPSTR pStack=(LPSTR)GlobalLock(hStack);
> // some obscure win3.0 API call
> SwitchStackTo(HIWORD(pStack),(UINT)(63L*1024L),0);
> // normal serialize code
> CFile f;
> if(f.Open(strFileName, CFile::modeRead))
> {
> CArchive ar(&f,CArchive::load);
> // hit F8 to crash.....
> ar >> m_pRootObject;
> }
> ar.Close();
> f.Close();
> SwitchStackBack();
> GlobalUnlock(hStack);
> GlobalFree(hStack);
> }
>
> The nature of serialize() is recursive and there is not much to do about
> that, I checked out MFC's source code and the CArchive and CRuntimeClass
> read/write code, there are some non-static local variables in the code
> that eat a little stack space for each recursive level. In my own
> serialize code I declared all locals as 'static'.
>
> I hope somebody can give some tips/hints, please don't tell me to:
> * use 32-bits (I know, but my customers don't)
> * change the structure of my object model (its to late for that)
> * stop using MFC (I like some parts of it)
>
> Thanks a lot....
>
> Bart van Haaff (barthaaf@docuaccess.nl)
> Senior Software Developer
> Document Access B.V.
> The Netherlands
>
>
| Вернуться в корень Архива
|